diff --git a/.github/workflows/fsb.yml b/.github/workflows/fsb.yml index f8a36ffa4..737f53401 100644 --- a/.github/workflows/fsb.yml +++ b/.github/workflows/fsb.yml @@ -22,7 +22,7 @@ jobs: strategy: matrix: rust: - - 1.47.0 # MSRV + - 1.41.0 # MSRV - stable target: - thumbv7em-none-eabi @@ -42,7 +42,7 @@ jobs: strategy: matrix: rust: - - 1.47.0 # MSRV + - 1.41.0 # MSRV - stable steps: - uses: actions/checkout@v1 @@ -54,5 +54,4 @@ jobs: - run: cargo check --all-features - run: cargo test --no-default-features - run: cargo test - - run: cargo test --features asm - run: cargo test --all-features diff --git a/.github/workflows/ripemd160.yml b/.github/workflows/ripemd.yml similarity index 94% rename from .github/workflows/ripemd160.yml rename to .github/workflows/ripemd.yml index 7d78d12d6..cf0ee5ff6 100644 --- a/.github/workflows/ripemd160.yml +++ b/.github/workflows/ripemd.yml @@ -1,16 +1,16 @@ -name: ripemd160 +name: ripemd on: pull_request: paths: - - "ripemd160/**" + - "ripemd/**" - "Cargo.*" push: branches: master defaults: run: - working-directory: ripemd160 + working-directory: ripemd env: CARGO_INCREMENTAL: 0 diff --git a/.github/workflows/ripemd256.yml b/.github/workflows/ripemd256.yml deleted file mode 100644 index 324f85b5e..000000000 --- a/.github/workflows/ripemd256.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: ripemd256 - -on: - pull_request: - paths: - - "ripemd256/**" - - "Cargo.*" - push: - branches: master - -defaults: - run: - working-directory: ripemd256 - -env: - CARGO_INCREMENTAL: 0 - RUSTFLAGS: "-Dwarnings" - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - rust: - - 1.41.0 # MSRV - - stable - target: - - thumbv7em-none-eabi - - wasm32-unknown-unknown - steps: - - uses: actions/checkout@v1 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - override: true - - run: cargo build --no-default-features --release --target ${{ matrix.target }} - - test: - runs-on: ubuntu-latest - strategy: - matrix: - rust: - - 1.41.0 # MSRV - - stable - steps: - - uses: actions/checkout@v1 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: ${{ matrix.rust }} - override: true - - run: cargo check --all-features - - run: cargo test --no-default-features - - run: cargo test - - run: cargo test --all-features - diff --git a/.github/workflows/ripemd320.yml b/.github/workflows/ripemd320.yml deleted file mode 100644 index dbd541b01..000000000 --- a/.github/workflows/ripemd320.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: ripemd320 - -on: - pull_request: - paths: - - "ripemd320/**" - - "Cargo.*" - push: - branches: master - -defaults: - run: - working-directory: ripemd320 - -env: - CARGO_INCREMENTAL: 0 - RUSTFLAGS: "-Dwarnings" - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - rust: - - 1.41.0 # MSRV - - stable - target: - - thumbv7em-none-eabi - - wasm32-unknown-unknown - steps: - - uses: actions/checkout@v1 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - override: true - - run: cargo build --no-default-features --release --target ${{ matrix.target }} - - test: - runs-on: ubuntu-latest - strategy: - matrix: - rust: - - 1.41.0 # MSRV - - stable - steps: - - uses: actions/checkout@v1 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: ${{ matrix.rust }} - override: true - - run: cargo check --all-features - - run: cargo test --no-default-features - - run: cargo test - - run: cargo test --all-features diff --git a/.github/workflows/sha2.yml b/.github/workflows/sha2.yml index 75ae8d9a6..0e2e34d70 100644 --- a/.github/workflows/sha2.yml +++ b/.github/workflows/sha2.yml @@ -129,6 +129,10 @@ jobs: rust: stable runs-on: ubuntu-latest + defaults: + run: + # Cross mounts only current package, i.e. by default it ignores workspace's Cargo.toml + working-directory: . steps: - uses: actions/checkout@v1 - uses: actions-rs/toolchain@v1 @@ -137,6 +141,11 @@ jobs: toolchain: ${{ matrix.rust }} target: ${{ matrix.target }} override: true - - run: cargo install cross - - run: cross test --target ${{ matrix.target }} --release - - run: cross test --target ${{ matrix.target }} --release --features asm + - name: Install precompiled cross + run: | + export URL=$(curl -s https://api.github.com/repos/rust-embedded/cross/releases/latest | jq -r '.assets[] | select(.name | contains("x86_64-unknown-linux-gnu.tar.gz")) | .browser_download_url') + wget -O /tmp/binaries.tar.gz $URL + tar -C /tmp -xzf /tmp/binaries.tar.gz + mv /tmp/cross ~/.cargo/bin + - run: cross test --package sha2 --target ${{ matrix.target }} --release + - run: cross test --package sha2 --target ${{ matrix.target }} --release --features asm diff --git a/Cargo.lock b/Cargo.lock index cba495698..fd7f57c1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,50 +4,31 @@ version = 3 [[package]] name = "blake2" -version = "0.9.2" +version = "0.10.0" dependencies = [ - "crypto-mac", "digest", "hex-literal", - "opaque-debug", ] [[package]] name = "blobby" -version = "0.1.2" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe5f8c2940b65859ece4b3b2ba02d2b12c87cab455fd42dee2556a187bb2cf6" -dependencies = [ - "byteorder", -] +checksum = "fc52553543ecb104069b0ff9e0fcc5c739ad16202935528a112d974e8f1a4ee8" [[package]] name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +version = "0.10.0" +source = "git+https://github.com/RustCrypto/utils?branch=block-buffer/v0.10#c47a851d747fa79df02567ab4d9faf40a1093855" dependencies = [ - "block-padding", "generic-array", ] -[[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - [[package]] name = "cc" -version = "1.0.69" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" [[package]] name = "cfg-if" @@ -65,34 +46,31 @@ dependencies = [ ] [[package]] -name = "crypto-mac" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +name = "crypto-common" +version = "0.1.0" +source = "git+https://github.com/RustCrypto/traits/?branch=digest/v0.10#6391acdb926578f0c0f7e4d4e0618c42f361aebf" dependencies = [ - "blobby", "generic-array", - "subtle", ] [[package]] name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +version = "0.10.0" +source = "git+https://github.com/RustCrypto/traits/?branch=digest/v0.10#6391acdb926578f0c0f7e4d4e0618c42f361aebf" dependencies = [ "blobby", + "block-buffer", + "crypto-common", "generic-array", + "subtle", ] [[package]] name = "fsb" -version = "0.0.2" +version = "0.1.0" dependencies = [ - "block-buffer", "digest", "hex-literal", - "opaque-debug", "whirlpool", ] @@ -108,22 +86,18 @@ dependencies = [ [[package]] name = "gost94" -version = "0.9.1" +version = "0.10.0" dependencies = [ - "block-buffer", "digest", "hex-literal", - "opaque-debug", ] [[package]] name = "groestl" -version = "0.9.0" +version = "0.10.0" dependencies = [ - "block-buffer", "digest", "hex-literal", - "opaque-debug", ] [[package]] @@ -147,7 +121,7 @@ dependencies = [ [[package]] name = "k12" -version = "0.1.0" +version = "0.2.0" dependencies = [ "digest", "hex-literal", @@ -161,56 +135,44 @@ checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" [[package]] name = "libc" -version = "0.2.101" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" +checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119" [[package]] name = "md-5" -version = "0.9.1" +version = "0.10.0" dependencies = [ - "block-buffer", "digest", "hex-literal", "md5-asm", - "opaque-debug", ] [[package]] name = "md2" -version = "0.9.0" +version = "0.10.0" dependencies = [ - "block-buffer", "digest", "hex-literal", - "opaque-debug", ] [[package]] name = "md4" -version = "0.9.0" +version = "0.10.0" dependencies = [ - "block-buffer", "digest", "hex-literal", - "opaque-debug", ] [[package]] name = "md5-asm" -version = "0.4.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b47e5a1261ecd6ba951d1ad392534743310e513ef1e2609023368798829f33e" +checksum = "73b9a6f25ec11ea27e22d7fc8beafda909da44ece95f63e94f1eeb23d19bb5c7" dependencies = [ "cc", ] -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -218,45 +180,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] -name = "ripemd160" -version = "0.9.1" -dependencies = [ - "block-buffer", - "digest", - "hex-literal", - "opaque-debug", -] - -[[package]] -name = "ripemd256" +name = "ripemd" version = "0.1.0" dependencies = [ - "block-buffer", - "digest", - "hex-literal", - "opaque-debug", -] - -[[package]] -name = "ripemd320" -version = "0.9.0" -dependencies = [ - "block-buffer", "digest", "hex-literal", - "opaque-debug", ] [[package]] name = "sha-1" -version = "0.9.8" +version = "0.10.0" dependencies = [ - "block-buffer", "cfg-if", "cpufeatures", "digest", "hex-literal", - "opaque-debug", "sha1-asm", ] @@ -271,14 +209,12 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.8" +version = "0.10.0" dependencies = [ - "block-buffer", "cfg-if", "cpufeatures", "digest", "hex-literal", - "opaque-debug", "sha2-asm", ] @@ -293,43 +229,35 @@ dependencies = [ [[package]] name = "sha3" -version = "0.9.1" +version = "0.10.0" dependencies = [ - "block-buffer", "digest", "hex-literal", "keccak", - "opaque-debug", ] [[package]] name = "shabal" -version = "0.3.0" +version = "0.4.0" dependencies = [ - "block-buffer", "digest", "hex-literal", - "opaque-debug", ] [[package]] name = "sm3" -version = "0.3.0" +version = "0.4.0" dependencies = [ - "block-buffer", "digest", "hex-literal", - "opaque-debug", ] [[package]] name = "streebog" -version = "0.9.2" +version = "0.10.0" dependencies = [ - "block-buffer", "digest", "hex-literal", - "opaque-debug", ] [[package]] @@ -340,19 +268,17 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "tiger" -version = "0.1.0" +version = "0.2.0" dependencies = [ - "block-buffer", - "byteorder", "digest", "hex-literal", ] [[package]] name = "typenum" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" [[package]] name = "version_check" @@ -362,20 +288,18 @@ checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" [[package]] name = "whirlpool" -version = "0.9.0" +version = "0.10.0" dependencies = [ - "block-buffer", "digest", "hex-literal", - "opaque-debug", "whirlpool-asm", ] [[package]] name = "whirlpool-asm" -version = "0.5.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbb23be8b0dec6fafef14563c42ec98bbfc33f2a97ed5bc99cd8b50ea5c68097" +checksum = "4b0930846e800a97c78fd09a494b25d1f0780be9face03b7a05151e3104a8284" dependencies = [ "cc", ] diff --git a/Cargo.toml b/Cargo.toml index 00547e603..91c900778 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,16 +1,14 @@ [workspace] members = [ - "fsb", "blake2", + "fsb", "gost94", "groestl", "k12", "md2", "md4", "md5", - "ripemd160", - "ripemd256", - "ripemd320", + "ripemd", "sha1", "sha2", "sha3", @@ -23,3 +21,7 @@ members = [ [profile.dev] opt-level = 2 + +[patch.crates-io] +digest = { git = "https://github.com/RustCrypto/traits/", branch = "digest/v0.10" } +block-buffer = { git = "https://github.com/RustCrypto/utils", branch = "block-buffer/v0.10" } diff --git a/README.md b/README.md index c2b1fb186..79f3ec283 100644 --- a/README.md +++ b/README.md @@ -1,99 +1,89 @@ -# RustCrypto: hashes [![Project Chat][chat-image]][chat-link] [![dependency status][deps-image]][deps-link] +# RustCrypto: Hashes [![Project Chat][chat-image]][chat-link] [![dependency status][deps-image]][deps-link] Collection of [cryptographic hash functions][1] written in pure Rust. -All algorithms reside in the separate crates and implemented using traits from -[`digest`](https://docs.rs/digest/) crate. Additionally all crates do not -require the standard library (i.e. `no_std` capable) and can be easily used for -bare-metal or WebAssembly programming. - -## Supported algorithms -**Note:** For new applications, or where compatibility with other existing -standards is not a primary concern, we strongly recommend to use either -BLAKE2, SHA-2 or SHA-3. - -| Name | Algorithm | Crates.io | Documentation | Build Status | [Security] | -|-------------|------------|-----------|---------------|--------------|------------| -| `blake2` | [BLAKE2] | [![crates.io](https://img.shields.io/crates/v/blake2.svg)](https://crates.io/crates/blake2) | [![Documentation](https://docs.rs/blake2/badge.svg)](https://docs.rs/blake2) | [![build](https://github.com/rustcrypto/hashes/workflows/blake2/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/hashes/actions?query=workflow:blake2+branch:master) | :green_heart: | -| `fsb` | [FSB] | [![crates.io](https://img.shields.io/crates/v/fsb.svg)](https://crates.io/crates/fsb) | [![Documentation](https://docs.rs/fsb/badge.svg)](https://docs.rs/fsb) | [![build](https://github.com/rustcrypto/hashes/workflows/fsb/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/fsb/actions?query=workflow:fsb+branch:master) | :green_heart: | -| `gost94` | [GOST94] (GOST R 34.11-94) | [![crates.io](https://img.shields.io/crates/v/gost94.svg)](https://crates.io/crates/gost94) | [![Documentation](https://docs.rs/gost94/badge.svg)](https://docs.rs/gost94) | [![build](https://github.com/rustcrypto/hashes/workflows/gost94/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/hashes/actions?query=workflow:gost94+branch:master) | :yellow_heart: | -| `groestl` | [Grøstl] (Groestl) | [![crates.io](https://img.shields.io/crates/v/groestl.svg)](https://crates.io/crates/groestl) | [![Documentation](https://docs.rs/groestl/badge.svg)](https://docs.rs/groestl) | [![build](https://github.com/rustcrypto/hashes/workflows/groestl/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/hashes/actions?query=workflow:groestl+branch:master) | :green_heart: | -| `k12` | [KangarooTwelve] | [![crates.io](https://img.shields.io/crates/v/k12.svg)](https://crates.io/crates/k12) | [![Documentation](https://docs.rs/k12/badge.svg)](https://docs.rs/k12) | [![build](https://github.com/rustcrypto/hashes/workflows/k12/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/hashes/actions?query=workflow:k12+branch:master) | :green_heart: | -| `md2` | [MD2] | [![crates.io](https://img.shields.io/crates/v/md2.svg)](https://crates.io/crates/md2) | [![Documentation](https://docs.rs/md2/badge.svg)](https://docs.rs/md2) | [![build](https://github.com/rustcrypto/hashes/workflows/md2/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/hashes/actions?query=workflow:md2+branch:master) | :broken_heart: | -| `md4` | [MD4] | [![crates.io](https://img.shields.io/crates/v/md4.svg)](https://crates.io/crates/md4) | [![Documentation](https://docs.rs/md4/badge.svg)](https://docs.rs/md4) | [![build](https://github.com/rustcrypto/hashes/workflows/md4/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/hashes/actions?query=workflow:md4+branch:master) | :broken_heart: | -| `md-5` [:exclamation:] | [MD5] | [![crates.io](https://img.shields.io/crates/v/md-5.svg)](https://crates.io/crates/md-5) | [![Documentation](https://docs.rs/md-5/badge.svg)](https://docs.rs/md-5) | [![build](https://github.com/rustcrypto/hashes/workflows/md5/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/hashes/actions?query=workflow:md5+branch:master) | :broken_heart: | -| `ripemd160` | [RIPEMD-160] | [![crates.io](https://img.shields.io/crates/v/ripemd160.svg)](https://crates.io/crates/ripemd160) | [![Documentation](https://docs.rs/ripemd160/badge.svg)](https://docs.rs/ripemd160) | [![build](https://github.com/rustcrypto/hashes/workflows/ripemd160/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/hashes/actions?query=workflow:ripemd160+branch:master) | :green_heart: | -| `ripemd256` | [RIPEMD-256] | [![crates.io](https://img.shields.io/crates/v/ripemd256.svg)](https://crates.io/crates/ripemd256) | [![Documentation](https://docs.rs/ripemd256/badge.svg)](https://docs.rs/ripemd256) | [![build](https://github.com/rustcrypto/hashes/workflows/ripemd256/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/hashes/actions?query=workflow:ripemd256+branch:master) | :green_heart:* | -| `ripemd320` | [RIPEMD-320] | [![crates.io](https://img.shields.io/crates/v/ripemd320.svg)](https://crates.io/crates/ripemd320) | [![Documentation](https://docs.rs/ripemd320/badge.svg)](https://docs.rs/ripemd320) | [![build](https://github.com/rustcrypto/hashes/workflows/ripemd320/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/hashes/actions?query=workflow:ripemd320+branch:master) | :green_heart:* | -| `sha-1` [:exclamation:] | [SHA-1] | [![crates.io](https://img.shields.io/crates/v/sha-1.svg)](https://crates.io/crates/sha-1) | [![Documentation](https://docs.rs/sha-1/badge.svg)](https://docs.rs/sha-1) | [![build](https://github.com/rustcrypto/hashes/workflows/sha1/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/hashes/actions?query=workflow:sha1+branch:master) | :broken_heart: | -| `sha2` | [SHA-2] | [![crates.io](https://img.shields.io/crates/v/sha2.svg)](https://crates.io/crates/sha2) | [![Documentation](https://docs.rs/sha2/badge.svg)](https://docs.rs/sha2) | [![build](https://github.com/rustcrypto/hashes/workflows/sha2/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/hashes/actions?query=workflow:sha2+branch:master) | :green_heart: | -| `sha3` | [SHA-3] (Keccak) | [![crates.io](https://img.shields.io/crates/v/sha3.svg)](https://crates.io/crates/sha3) | [![Documentation](https://docs.rs/sha3/badge.svg)](https://docs.rs/sha3) | [![build](https://github.com/rustcrypto/hashes/workflows/sha3/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/hashes/actions?query=workflow:sha3+branch:master) | :green_heart: | -| `shabal` | [SHABAL] | [![crates.io](https://img.shields.io/crates/v/shabal.svg)](https://crates.io/crates/shabal) | [![Documentation](https://docs.rs/shabal/badge.svg)](https://docs.rs/shabal) | [![build](https://github.com/rustcrypto/hashes/workflows/shabal/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/hashes/actions?query=workflow:shabal+branch:master) | :green_heart: | -| `sm3` | [SM3 (OSCCA GM/T 0004-2012)][SM3] | [![crates.io](https://img.shields.io/crates/v/sm3.svg)](https://crates.io/crates/sm3) | [![Documentation](https://docs.rs/sm3/badge.svg)](https://docs.rs/sm3) | [![build](https://github.com/rustcrypto/hashes/workflows/sm3/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/hashes/actions?query=workflow:sm3+branch:master) | :green_heart: | -| `streebog` | [Streebog] (GOST R 34.11-2012) | [![crates.io](https://img.shields.io/crates/v/streebog.svg)](https://crates.io/crates/streebog) | [![Documentation](https://docs.rs/streebog/badge.svg)](https://docs.rs/streebog) | [![build](https://github.com/rustcrypto/hashes/workflows/streebog/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/hashes/actions?query=workflow:streebog+branch:master) | :yellow_heart: | -| `tiger` | [Tiger] | [![crates.io](https://img.shields.io/crates/v/tiger.svg)](https://crates.io/crates/tiger) | [![Documentation](https://docs.rs/tiger/badge.svg)](https://docs.rs/tiger) | [![build](https://github.com/rustcrypto/hashes/workflows/tiger/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/hashes/actions?query=workflow:tiger+branch:master) | :green_heart: | -| `whirlpool` | [Whirlpool] | [![crates.io](https://img.shields.io/crates/v/whirlpool.svg)](https://crates.io/crates/whirlpool) | [![Documentation](https://docs.rs/whirlpool/badge.svg)](https://docs.rs/whirlpool) | [![build](https://github.com/rustcrypto/hashes/workflows/whirlpool/badge.svg?branch=master&event=push)](https://github.com/RustCrypto/hashes/actions?query=workflow:whirlpool+branch:master) | :green_heart: | - -NOTE: the [BLAKE3 crate](https://github.com/BLAKE3-team/BLAKE3) implements the `digest` (and `crypto-mac`) traits used by the rest of the hashes in this repository, but is maintained by the BLAKE3 team. - -\* RIPEMD-256 provides only the same security as RIPEMD-128, and RIPEMD-320 provides only the same security as RIPEMD-160 +All algorithms reside in the separate crates and implemented using traits from [`digest`](https://docs.rs/digest/) crate. +Additionally all crates do not require the standard library (i.e. `no_std` capable) and can be easily used for bare-metal or WebAssembly programming. + +## Supported Algorithms + +**Note:** For new applications, or where compatibility with other existing standards is not a primary concern, we strongly recommend to use either BLAKE2, SHA-2 or SHA-3. + +| Algorithm | Crate | Crates.io | Documentation | MSRV | [Security] | +|-----------|-------|:---------:|:-------------:|:----:|:----------:| +| [BLAKE2] | `blake2` | [![crates.io](https://img.shields.io/crates/v/blake2.svg)](https://crates.io/crates/blake2) | [![Documentation](https://docs.rs/blake2/badge.svg)](https://docs.rs/blake2) | ![Minimum Supported Rust Version][msrv-1.41] | :green_heart: | +| [FSB] | `fsb` | [![crates.io](https://img.shields.io/crates/v/fsb.svg)](https://crates.io/crates/fsb) | [![Documentation](https://docs.rs/fsb/badge.svg)](https://docs.rs/fsb) | ![Minimum Supported Rust Version][msrv-1.41] | :green_heart: | +| [GOST R 34.11-94][GOST94] | `gost94` | [![crates.io](https://img.shields.io/crates/v/gost94.svg)](https://crates.io/crates/gost94) | [![Documentation](https://docs.rs/gost94/badge.svg)](https://docs.rs/gost94) | ![Minimum Supported Rust Version][msrv-1.41] | :yellow_heart: | +| [Grøstl] (Groestl) | `groestl` | [![crates.io](https://img.shields.io/crates/v/groestl.svg)](https://crates.io/crates/groestl) | [![Documentation](https://docs.rs/groestl/badge.svg)](https://docs.rs/groestl) | ![Minimum Supported Rust Version][msrv-1.41] | :green_heart: | +| [KangarooTwelve] | `k12` | [![crates.io](https://img.shields.io/crates/v/k12.svg)](https://crates.io/crates/k12) | [![Documentation](https://docs.rs/k12/badge.svg)](https://docs.rs/k12) | ![Minimum Supported Rust Version][msrv-1.41] | :green_heart: | +| [MD2] | `md2` | [![crates.io](https://img.shields.io/crates/v/md2.svg)](https://crates.io/crates/md2) | [![Documentation](https://docs.rs/md2/badge.svg)](https://docs.rs/md2) | ![Minimum Supported Rust Version][msrv-1.41] | :broken_heart: | +| [MD4] | `md4` | [![crates.io](https://img.shields.io/crates/v/md4.svg)](https://crates.io/crates/md4) | [![Documentation](https://docs.rs/md4/badge.svg)](https://docs.rs/md4) | ![Minimum Supported Rust Version][msrv-1.41] | :broken_heart: | +| [MD5] | `md-5` [:exclamation:] | [![crates.io](https://img.shields.io/crates/v/md-5.svg)](https://crates.io/crates/md-5) | [![Documentation](https://docs.rs/md-5/badge.svg)](https://docs.rs/md-5) | ![Minimum Supported Rust Version][msrv-1.41] | :broken_heart: | +| [RIPEMD] | `ripemd` | [![crates.io](https://img.shields.io/crates/v/ripemd.svg)](https://crates.io/crates/ripemd) | [![Documentation](https://docs.rs/ripemd/badge.svg)](https://docs.rs/ripemd) | ![Minimum Supported Rust Version][msrv-1.41] | :green_heart: | +| [SHA-1] | `sha-1` [:exclamation:] | [![crates.io](https://img.shields.io/crates/v/sha-1.svg)](https://crates.io/crates/sha-1) | [![Documentation](https://docs.rs/sha-1/badge.svg)](https://docs.rs/sha-1) | ![Minimum Supported Rust Version][msrv-1.41] | :broken_heart: | +| [SHA-2] | `sha2` | [![crates.io](https://img.shields.io/crates/v/sha2.svg)](https://crates.io/crates/sha2) | [![Documentation](https://docs.rs/sha2/badge.svg)](https://docs.rs/sha2) | ![Minimum Supported Rust Version][msrv-1.41] | :green_heart: | +| [SHA-3] (Keccak) | `sha3` | [![crates.io](https://img.shields.io/crates/v/sha3.svg)](https://crates.io/crates/sha3) | [![Documentation](https://docs.rs/sha3/badge.svg)](https://docs.rs/sha3) | ![Minimum Supported Rust Version][msrv-1.41] | :green_heart: | +| [SHABAL] | `shabal` | [![crates.io](https://img.shields.io/crates/v/shabal.svg)](https://crates.io/crates/shabal) | [![Documentation](https://docs.rs/shabal/badge.svg)](https://docs.rs/shabal) | ![Minimum Supported Rust Version][msrv-1.41] | :green_heart: | +| [SM3] (OSCCA GM/T 0004-2012) | `sm3` | [![crates.io](https://img.shields.io/crates/v/sm3.svg)](https://crates.io/crates/sm3) | [![Documentation](https://docs.rs/sm3/badge.svg)](https://docs.rs/sm3) | ![Minimum Supported Rust Version][msrv-1.41] | :green_heart: | +| [Streebog] (GOST R 34.11-2012) | `streebog` | [![crates.io](https://img.shields.io/crates/v/streebog.svg)](https://crates.io/crates/streebog) | [![Documentation](https://docs.rs/streebog/badge.svg)](https://docs.rs/streebog) | ![Minimum Supported Rust Version][msrv-1.41] | :yellow_heart: | +| [Tiger] | `tiger` | [![crates.io](https://img.shields.io/crates/v/tiger.svg)](https://crates.io/crates/tiger) | [![Documentation](https://docs.rs/tiger/badge.svg)](https://docs.rs/tiger) | ![Minimum Supported Rust Version][msrv-1.41] | :green_heart: | +| [Whirlpool] | `whirlpool` | [![crates.io](https://img.shields.io/crates/v/whirlpool.svg)](https://crates.io/crates/whirlpool) | [![Documentation](https://docs.rs/whirlpool/badge.svg)](https://docs.rs/whirlpool) | ![Minimum Supported Rust Version][msrv-1.41] | :green_heart: | + +NOTE: the [BLAKE3 crate](https://github.com/BLAKE3-team/BLAKE3) implements the `digest` traits used by the rest of the hashes in this repository, but is maintained by the BLAKE3 team. [Security]: https://en.wikipedia.org/wiki/Hash_function_security_summary [:exclamation:]: #crate-names -### Crate names -Whenever possible crates are published under the the same name as the crate -folder. Owners of `md5` and `sha1` crates declined -([1](https://github.com/stainless-steel/md5/pull/2), -[2](https://github.com/mitsuhiko/rust-sha1/issues/17)) to participate in this -project. This is why crates marked by :exclamation: are published under -`md-5` and `sha-1` names respectively. +### Crate Names + +Whenever possible crates are published under the the same name as the crate folder. +Owners of `md5` and `sha1` crates declined ([1](https://github.com/stainless-steel/md5/pull/2), [2](https://github.com/mitsuhiko/rust-sha1/issues/17)) to participate in this project +Those crates do not implement the [`digest`] traits, so they are not interoperable with the RustCrypto ecosystem. +This is why crates marked by :exclamation: are published under `md-5` and `sha-1` names respectively. ### Security Level Legend -The following describes the security level ratings associated with each -hash function (i.e. algorithms, not the specific implementation): + +The following describes the security level ratings associated with each hash function (i.e. algorithms, not the specific implementation): | Heart | Description | -|----------------|-------------| +|:--------------:|-------------| | :green_heart: | No known successful attacks | | :yellow_heart: | Theoretical break: security lower than claimed | | :broken_heart: | Attack demonstrated in practice: avoid if at all possible | See the [Security] page on Wikipedia for more information. -### Minimum Supported Rust Version (MSRV) -All crates in this repository support Rust 1.21 or higher. In future -minimally supported version of Rust can be changed, but it will be done with -a minor version bump. +### Minimum Supported Rust Version (MSRV) Policy + +MSRV bumps are considered breaking changes and will be performed only with minor version bump. ## Usage -Let us demonstrate how to use crates in this repository using BLAKE2b as an -example. -First add `blake2` crate to your `Cargo.toml`: +Let us demonstrate how to use crates in this repository using SHA-2 as an example. + +First add `sha2` crate to your `Cargo.toml`: ```toml [dependencies] -blake2 = "0.9" +sha2 = "0.10" ``` -Note that crates in this repository have an enabled by default `std` feature. +Note that all crates in this repository have an enabled by default `std` feature. So if you plan to use the crate in `no_std` environments, don't forget to disable it: ```toml [dependencies] -blake2 = { version="0.9", default-features = false } +sha2 = { version = "0.10", default-features = false } ``` -`blake2` and other crates re-export `digest` crate and `Digest` trait for -convenience, so you don't have to add `digest` crate as an explicit dependency. +`sha2` and other crates re-export the `digest` crate and the `Digest` trait for convenience, so you don't have to add `digest` crate as an explicit dependency. Now you can write the following code: -```Rust -use blake2::{Blake2b, Digest}; +```rust +use sha2::{Sha256, Digest}; -let mut hasher = Blake2b::new(); +let mut hasher = Sha256::new(); let data = b"Hello world!"; hasher.update(data); // `update` can be called repeatedly and is generic over `AsRef<[u8]>` @@ -103,64 +93,56 @@ let hash = hasher.finalize(); println!("Result: {:x}", hash); ``` -In this example `hash` has type [`GenericArray`][2], which is a generic -alternative to `[u8; 64]`. +In this example `hash` has type `GenericArray`, which is a generic alternative to `[u8; 32]` defined in the [`generic-array`] crate. -Alternatively you can use chained approach, which is equivalent to the previous -example: +Alternatively, you can use chained approach, which is equivalent to the previous example: -```Rust -use blake2::{Blake2b, Digest}; +```rust +use sha2::{Sha256, Digest}; -let hash = Blake2b::new() +let hash = Sha256::new() .chain(b"Hello world!") .chain("String data") .finalize(); println!("Result: {:x}", hash); ``` -If the whole message is available you also can use convenience `digest` method: +If a complete message is available, then you also can use the convenience `digest` method: -```Rust -use blake2::{Blake2b, Digest}; +```rust +use sha2::{Sha256, Digest}; -let hash = Blake2b::digest(b"my message"); +let hash = Sha256::digest(b"my message"); println!("Result: {:x}", hash); ``` -### Hashing `Read`able objects +### Hashing `Read`able Objects -If you want to hash data from [`Read`][3] trait (e.g. from file) you can rely on -implementation of [`Write`][4] trait (requires an enabled-by-default `std` feature): +If you want to hash data from a type which imlements the [`Read`] trait, you can rely on implementation of the [`Write`] trait (requires enabled-by-default `std` feature): -```Rust -use blake2::{Blake2b, Digest}; +```rust +use sha2::{Sha256, Digest}; use std::{fs, io}; let mut file = fs::File::open(&path)?; -let mut hasher = Blake2b::new(); +let mut hasher = Sha256::new(); let n = io::copy(&mut file, &mut hasher)?; let hash = hasher.finalize(); -println!("Path: {}", path); + println!("Bytes processed: {}", n); println!("Hash value: {:x}", hash); ``` ### Hash-based Message Authentication Code (HMAC) -If you want to calculate [Hash-based Message Authentication Code][5] (HMAC), -you can use generic implementation from [`hmac`](https://docs.rs/hmac) crate, -which is a part of the [RustCrypto/MACs][6] repository. +If you want to calculate [Hash-based Message Authentication Code][HMAC] (HMAC), you can use the generic implementation from [`hmac`] crate, which is a part of the [RustCrypto/MACs] repository. -### Generic code +### Generic Code -You can write generic code over `Digest` (or other traits from `digest` crate) -trait which will work over different hash functions: +You can write generic code over the `Digest` trait (or other traits from the `digest` crate) which will work over different hash functions: -```Rust -use digest::Digest; -use blake2::Blake2b; -use sha2::Sha256; +```rust +use sha2::{Sha256, Sha512, Digest}; // Toy example, do not use it in practice! // Instead use crates from: https://github.com/RustCrypto/password-hashing @@ -172,15 +154,31 @@ fn hash_password(password: &str, salt: &str, output: &mut [u8]) { output.copy_from_slice(&hasher.finalize()) } -let mut buf1 = [0u8; 64]; -hash_password::("my_password", "abcd", &mut buf1); +let mut buf1 = [0u8; 32]; +hash_password::("my_password", "abcd", &mut buf1); -let mut buf2 = [0u8; 32]; -hash_password::("my_password", "abcd", &mut buf2); +let mut buf2 = [0u8; 64]; +hash_password::("my_password", "abcd", &mut buf2); ``` -If you want to use hash functions with trait objects, use `digest::DynDigest` -trait. +If you want to use hash functions with trait objects, you can use the [`DynDigest`] trait: + +```rust +use sha2::{Sha256, Sha512, digest::DynDigest}; + +fn dyn_hash(hasher: &mut dyn DynDigest, data: &[u8]) -> Box<[u8]> { + hasher.update(data); + hasher.finalize_reset() +} + +let mut sha256_hasher = Sha256::default(); +let mut sha512_hasher = Sha512::default(); + +let res1 = dyn_hash(&mut sha256_hasher, b"foo"); +let res2 = dyn_hash(&mut sha256_hasher, b"bar"); +let res3 = dyn_hash(&mut sha512_hasher, b"foo"); +let res4 = dyn_hash(&mut sha512_hasher, b"bar"); +``` ## License @@ -193,9 +191,7 @@ at your option. ### Contribution -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in the work by you, as defined in the Apache-2.0 license, shall be -dual licensed as above, without any additional terms or conditions. +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. [//]: # (badges) @@ -203,15 +199,18 @@ dual licensed as above, without any additional terms or conditions. [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260041-hashes [deps-image]: https://deps.rs/repo/github/RustCrypto/hashes/status.svg [deps-link]: https://deps.rs/repo/github/RustCrypto/hashes +[msrv-1.41]: https://img.shields.io/badge/rustc-1.41.0+-blue.svg [//]: # (footnotes) [1]: https://en.wikipedia.org/wiki/Cryptographic_hash_function -[2]: https://docs.rs/generic-array -[3]: https://doc.rust-lang.org/std/io/trait.Read.html -[4]: https://doc.rust-lang.org/std/io/trait.Write.html -[5]: https://en.wikipedia.org/wiki/Hash-based_message_authentication_code -[6]: https://github.com/RustCrypto/MACs +[`generic-array`]: https://docs.rs/generic-array +[HMAC]: https://en.wikipedia.org/wiki/Hash-based_message_authentication_code +[`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +[`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html +[`hmac`]: https://docs.rs/hmac +[RustCrypto/MACs]: https://github.com/RustCrypto/MACs +[`DynDigest`]: https://docs.rs/digest/0.10.0/digest/trait.DynDigest.html [//]: # (algorithms) @@ -223,9 +222,7 @@ dual licensed as above, without any additional terms or conditions. [MD2]: https://en.wikipedia.org/wiki/MD2_(cryptography) [MD4]: https://en.wikipedia.org/wiki/MD4 [MD5]: https://en.wikipedia.org/wiki/MD5 -[RIPEMD-160]: https://en.wikipedia.org/wiki/RIPEMD -[RIPEMD-256]: https://en.wikipedia.org/wiki/RIPEMD -[RIPEMD-320]: https://en.wikipedia.org/wiki/RIPEMD +[RIPEMD]: https://en.wikipedia.org/wiki/RIPEMD [SHA-1]: https://en.wikipedia.org/wiki/SHA-1 [SHA-2]: https://en.wikipedia.org/wiki/SHA-2 [SHA-3]: https://en.wikipedia.org/wiki/SHA-3 diff --git a/blake2/CHANGELOG.md b/blake2/CHANGELOG.md index 60bf2e2dd..4e6351605 100644 --- a/blake2/CHANGELOG.md +++ b/blake2/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## 0.10.0 (2021-11-22) +### Changed +- Update to `digest` v0.10 and remove dependency on `crypto-mac` ([#217]) + +[#217]: https://github.com/RustCrypto/hashes/pull/217 + ## 0.9.2 (2021-08-25) ### Fixed - Building with `simd_opt` on recent nightlies ([#301]) diff --git a/blake2/Cargo.toml b/blake2/Cargo.toml index 6d25e15a7..45f8c94cc 100644 --- a/blake2/Cargo.toml +++ b/blake2/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "blake2" -version = "0.9.2" +name = "blake2" # Also update html_root_url in lib.rs when bumping this +version = "0.10.0" # Also update html_root_url in lib.rs when bumping this description = "BLAKE2 hash functions" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -12,18 +12,15 @@ keywords = ["crypto", "blake2", "hash", "digest"] categories = ["cryptography", "no-std"] [dependencies] -digest = "0.9" -crypto-mac = "0.8" -opaque-debug = "0.3" +digest = { version = "0.10", features = ["mac"] } [dev-dependencies] -digest = { version = "0.9", features = ["dev"] } -crypto-mac = { version = "0.8", features = ["dev"] } +digest = { version = "0.10", features = ["dev"] } hex-literal = "0.2" [features] default = ["std"] -std = ["digest/std", "crypto-mac/std"] +std = ["digest/std"] simd = [] simd_opt = ["simd"] simd_asm = ["simd_opt"] diff --git a/blake2/examples/blake2b_sum.rs b/blake2/examples/blake2b_sum.rs deleted file mode 100644 index 31e0ff11e..000000000 --- a/blake2/examples/blake2b_sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use blake2::{Blake2b, Digest}; -use std::env; -use std::fs; -use std::io::{self, Read}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = D::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/blake2/examples/blake2s_sum.rs b/blake2/examples/blake2s_sum.rs deleted file mode 100644 index 38be51d03..000000000 --- a/blake2/examples/blake2s_sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use blake2::{Blake2s, Digest}; -use std::env; -use std::fs; -use std::io::{self, Read}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = D::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/blake2/src/blake2.rs b/blake2/src/blake2.rs deleted file mode 100644 index 3255a30e9..000000000 --- a/blake2/src/blake2.rs +++ /dev/null @@ -1,414 +0,0 @@ -macro_rules! blake2_impl { - ( - $state:ident, $fix_state:ident, $word:ident, $vec:ident, $bytes:ident, - $block_size:ident, $R1:expr, $R2:expr, $R3:expr, $R4:expr, $IV:expr, - $vardoc:expr, $doc:expr, - ) => { - use $crate::as_bytes::AsBytes; - use $crate::simd::{$vec, Vector4}; - - use core::{cmp, convert::TryInto, ops::Div}; - use crypto_mac::{InvalidKeyLength, Mac, NewMac}; - use digest::generic_array::typenum::{Unsigned, U4}; - use digest::generic_array::GenericArray; - use digest::InvalidOutputSize; - use digest::{BlockInput, FixedOutputDirty, Reset, Update, VariableOutputDirty}; - - type Output = GenericArray; - - #[derive(Clone)] - #[doc=$vardoc] - pub struct $state { - m: [$word; 16], - h: [$vec; 2], - t: u64, - n: usize, - - h0: [$vec; 2], - m0: [$word; 16], - t0: u64, - } - - #[inline(always)] - fn iv0() -> $vec { - $vec::new($IV[0], $IV[1], $IV[2], $IV[3]) - } - #[inline(always)] - fn iv1() -> $vec { - $vec::new($IV[4], $IV[5], $IV[6], $IV[7]) - } - - #[inline(always)] - fn quarter_round(v: &mut [$vec; 4], rd: u32, rb: u32, m: $vec) { - v[0] = v[0].wrapping_add(v[1]).wrapping_add(m.from_le()); - v[3] = (v[3] ^ v[0]).rotate_right_const(rd); - v[2] = v[2].wrapping_add(v[3]); - v[1] = (v[1] ^ v[2]).rotate_right_const(rb); - } - - #[inline(always)] - fn shuffle(v: &mut [$vec; 4]) { - v[1] = v[1].shuffle_left_1(); - v[2] = v[2].shuffle_left_2(); - v[3] = v[3].shuffle_left_3(); - } - - #[inline(always)] - fn unshuffle(v: &mut [$vec; 4]) { - v[1] = v[1].shuffle_right_1(); - v[2] = v[2].shuffle_right_2(); - v[3] = v[3].shuffle_right_3(); - } - - #[inline(always)] - fn round(v: &mut [$vec; 4], m: &[$word; 16], s: &[usize; 16]) { - quarter_round(v, $R1, $R2, $vec::gather(m, s[0], s[2], s[4], s[6])); - quarter_round(v, $R3, $R4, $vec::gather(m, s[1], s[3], s[5], s[7])); - - shuffle(v); - quarter_round(v, $R1, $R2, $vec::gather(m, s[8], s[10], s[12], s[14])); - quarter_round(v, $R3, $R4, $vec::gather(m, s[9], s[11], s[13], s[15])); - unshuffle(v); - } - - impl $state { - /// Creates a new hashing context with a key. - /// - /// **WARNING!** If you plan to use it for variable output MAC, then - /// make sure to compare codes in constant time! It can be done - /// for example by using `subtle` crate. - pub fn new_keyed(key: &[u8], output_size: usize) -> Self { - Self::with_params(key, &[], &[], output_size) - } - - /// Creates a new hashing context with the full set of sequential-mode parameters. - pub fn with_params( - key: &[u8], - salt: &[u8], - persona: &[u8], - output_size: usize, - ) -> Self { - let kk = key.len(); - assert!(kk <= $bytes::to_usize()); - assert!(output_size <= $bytes::to_usize()); - - // The number of bytes needed to express two words. - let length = $bytes::to_usize() / 4; - assert!(salt.len() <= length); - assert!(persona.len() <= length); - - // Build a parameter block - let mut p = [0 as $word; 8]; - p[0] = 0x0101_0000 ^ ((kk as $word) << 8) ^ (output_size as $word); - - // salt is two words long - if salt.len() < length { - let mut padded_salt = - GenericArray::>::Output>::default(); - for i in 0..salt.len() { - padded_salt[i] = salt[i]; - } - p[4] = $word::from_le_bytes(padded_salt[0..length / 2].try_into().unwrap()); - p[5] = $word::from_le_bytes( - padded_salt[length / 2..padded_salt.len()] - .try_into() - .unwrap(), - ); - } else { - p[4] = $word::from_le_bytes(salt[0..salt.len() / 2].try_into().unwrap()); - p[5] = - $word::from_le_bytes(salt[salt.len() / 2..salt.len()].try_into().unwrap()); - } - - // persona is also two words long - if persona.len() < length { - let mut padded_persona = - GenericArray::>::Output>::default(); - for i in 0..persona.len() { - padded_persona[i] = persona[i]; - } - p[6] = $word::from_le_bytes(padded_persona[0..length / 2].try_into().unwrap()); - p[7] = $word::from_le_bytes( - padded_persona[length / 2..padded_persona.len()] - .try_into() - .unwrap(), - ); - } else { - p[6] = $word::from_le_bytes(persona[0..length / 2].try_into().unwrap()); - p[7] = $word::from_le_bytes( - persona[length / 2..persona.len()].try_into().unwrap(), - ); - } - - let mut state = Self::with_parameter_block(&p); - - if kk > 0 { - copy(key, state.m.as_mut_bytes()); - state.t = 2 * $bytes::to_u64(); - } - - state.t0 = state.t; - state.m0 = state.m; - state - } - - #[doc(hidden)] - pub fn with_parameter_block(p: &[$word; 8]) -> Self { - let nn = p[0] as u8 as usize; - let kk = (p[0] >> 8) as u8 as usize; - assert!(nn >= 1 && nn <= $bytes::to_usize()); - assert!(kk <= $bytes::to_usize()); - - let h0 = [ - iv0() ^ $vec::new(p[0], p[1], p[2], p[3]), - iv1() ^ $vec::new(p[4], p[5], p[6], p[7]), - ]; - - $state { - m: [0; 16], - h: h0, - t: 0, - n: nn, - - t0: 0, - m0: [0; 16], - h0, - } - } - - /// Updates the hashing context with more data. - fn update(&mut self, data: &[u8]) { - let mut rest = data; - - let block = 2 * $bytes::to_usize(); - - let off = self.t as usize % block; - if off != 0 || self.t == 0 { - let len = cmp::min(block - off, rest.len()); - - let part = &rest[..len]; - rest = &rest[part.len()..]; - - copy(part, &mut self.m.as_mut_bytes()[off..]); - self.t = self - .t - .checked_add(part.len() as u64) - .expect("hash data length overflow"); - } - - while rest.len() >= block { - self.compress(0, 0); - - let part = &rest[..block]; - rest = &rest[part.len()..]; - - copy(part, &mut self.m.as_mut_bytes()); - self.t = self - .t - .checked_add(part.len() as u64) - .expect("hash data length overflow"); - } - - let n = rest.len(); - if n > 0 { - self.compress(0, 0); - - copy(rest, &mut self.m.as_mut_bytes()); - self.t = self - .t - .checked_add(rest.len() as u64) - .expect("hash data length overflow"); - } - } - - #[doc(hidden)] - pub fn finalize_last_node(mut self) -> Output { - self.finalize_with_flag(!0) - } - - fn finalize_with_flag(&mut self, f1: $word) -> Output { - let off = self.t as usize % (2 * $bytes::to_usize()); - if off != 0 { - self.m.as_mut_bytes()[off..].iter_mut().for_each(|b| *b = 0); - } - - self.compress(!0, f1); - - let buf = [self.h[0].to_le(), self.h[1].to_le()]; - - let mut out = GenericArray::default(); - copy(buf.as_bytes(), &mut out); - out - } - - fn compress(&mut self, f0: $word, f1: $word) { - use $crate::consts::SIGMA; - - let m = &self.m; - let h = &mut self.h; - - let t0 = self.t as $word; - let t1 = match $bytes::to_u8() { - 64 => 0, - 32 => (self.t >> 32) as $word, - _ => unreachable!(), - }; - - let mut v = [h[0], h[1], iv0(), iv1() ^ $vec::new(t0, t1, f0, f1)]; - - round(&mut v, m, &SIGMA[0]); - round(&mut v, m, &SIGMA[1]); - round(&mut v, m, &SIGMA[2]); - round(&mut v, m, &SIGMA[3]); - round(&mut v, m, &SIGMA[4]); - round(&mut v, m, &SIGMA[5]); - round(&mut v, m, &SIGMA[6]); - round(&mut v, m, &SIGMA[7]); - round(&mut v, m, &SIGMA[8]); - round(&mut v, m, &SIGMA[9]); - if $bytes::to_u8() == 64 { - round(&mut v, m, &SIGMA[0]); - round(&mut v, m, &SIGMA[1]); - } - - h[0] = h[0] ^ (v[0] ^ v[2]); - h[1] = h[1] ^ (v[1] ^ v[3]); - } - } - - impl Default for $state { - fn default() -> Self { - Self::new_keyed(&[], $bytes::to_usize()) - } - } - - impl BlockInput for $state { - type BlockSize = $block_size; - } - - impl Update for $state { - fn update(&mut self, data: impl AsRef<[u8]>) { - self.update(data.as_ref()); - } - } - - impl VariableOutputDirty for $state { - fn new(output_size: usize) -> Result { - if output_size == 0 || output_size > $bytes::to_usize() { - return Err(InvalidOutputSize); - } - Ok(Self::new_keyed(&[], output_size)) - } - - fn output_size(&self) -> usize { - self.n - } - - fn finalize_variable_dirty(&mut self, f: impl FnOnce(&[u8])) { - let n = self.n; - let res = self.finalize_with_flag(0); - f(&res[..n]); - } - } - - impl Reset for $state { - fn reset(&mut self) { - self.t = self.t0; - self.m = self.m0; - self.h = self.h0; - } - } - - opaque_debug::implement!($state); - digest::impl_write!($state); - - #[derive(Clone)] - #[doc=$doc] - pub struct $fix_state { - state: $state, - } - - impl $fix_state { - /// Creates a new hashing context with the full set of sequential-mode parameters. - pub fn with_params(key: &[u8], salt: &[u8], persona: &[u8]) -> Self { - let state = $state::with_params(key, salt, persona, $bytes::to_usize()); - Self { state } - } - } - - impl Default for $fix_state { - fn default() -> Self { - let state = $state::new_keyed(&[], $bytes::to_usize()); - Self { state } - } - } - - impl BlockInput for $fix_state { - type BlockSize = $block_size; - } - - impl Update for $fix_state { - fn update(&mut self, data: impl AsRef<[u8]>) { - self.state.update(data.as_ref()); - } - } - - impl FixedOutputDirty for $fix_state { - type OutputSize = $bytes; - - fn finalize_into_dirty(&mut self, out: &mut Output) { - out.copy_from_slice(&self.state.finalize_with_flag(0)); - } - } - - impl Reset for $fix_state { - fn reset(&mut self) { - self.state.reset() - } - } - - impl NewMac for $fix_state { - type KeySize = $bytes; - - fn new(key: &GenericArray) -> Self { - let state = $state::new_keyed(key, $bytes::to_usize()); - Self { state } - } - - fn new_varkey(key: &[u8]) -> Result { - if key.len() > $bytes::to_usize() { - Err(InvalidKeyLength) - } else { - let state = $state::new_keyed(key, $bytes::to_usize()); - Ok(Self { state }) - } - } - } - - impl Mac for $fix_state { - type OutputSize = $bytes; - - fn update(&mut self, data: &[u8]) { - self.state.update(data); - } - - fn reset(&mut self) { - ::reset(self) - } - - fn finalize(mut self) -> crypto_mac::Output { - crypto_mac::Output::new(self.state.finalize_with_flag(0)) - } - } - - opaque_debug::implement!($fix_state); - digest::impl_write!($fix_state); - - fn copy(src: &[u8], dst: &mut [u8]) { - assert!(dst.len() >= src.len()); - unsafe { - core::ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len()); - } - } - }; -} diff --git a/blake2/src/blake2b.rs b/blake2/src/blake2b.rs deleted file mode 100644 index 3afc18d84..000000000 --- a/blake2/src/blake2b.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::consts::BLAKE2B_IV; -use digest::generic_array::typenum::{U128, U64}; - -blake2_impl!( - VarBlake2b, - Blake2b, - u64, - u64x4, - U64, - U128, - 32, - 24, - 16, - 63, - BLAKE2B_IV, - "Blake2b instance with a variable output.", - "Blake2b instance with a fixed output.", -); diff --git a/blake2/src/blake2s.rs b/blake2/src/blake2s.rs deleted file mode 100644 index 5306ed992..000000000 --- a/blake2/src/blake2s.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::consts::BLAKE2S_IV; -use digest::generic_array::typenum::{U32, U64}; - -blake2_impl!( - VarBlake2s, - Blake2s, - u32, - u32x4, - U32, - U64, - 16, - 12, - 8, - 7, - BLAKE2S_IV, - "Blake2s instance with a variable output.", - "Blake2s instance with a fixed output.", -); diff --git a/blake2/src/lib.rs b/blake2/src/lib.rs index b74c7b5bf..6d153cba4 100644 --- a/blake2/src/lib.rs +++ b/blake2/src/lib.rs @@ -2,14 +2,14 @@ //! //! # Usage //! -//! `Blake2b` can be used in the following way: +//! [`Blake2b512`] and [`Blake2s256`] can be used in the following way: //! //! ```rust -//! use blake2::{Blake2b, Blake2s, Digest}; +//! use blake2::{Blake2b512, Blake2s256, Digest}; //! use hex_literal::hex; //! -//! // create a Blake2b object -//! let mut hasher = Blake2b::new(); +//! // create a Blake2b512 object +//! let mut hasher = Blake2b512::new(); //! //! // write input message //! hasher.update(b"hello world"); @@ -21,8 +21,8 @@ //! c05a037cddbed06e309bf334942c4e58cdf1a46e237911ccd7fcf9787cbc7fd0 //! ")[..]); //! -//! // same example for `Blake2s`: -//! let mut hasher = Blake2s::new(); +//! // same example for Blake2s256: +//! let mut hasher = Blake2s256::new(); //! hasher.update(b"hello world"); //! let res = hasher.finalize(); //! assert_eq!(res[..], hex!(" @@ -34,45 +34,32 @@ //! //! ## Variable output size //! -//! If you need variable sized output you can use `VarBlake2b` and `VarBlake2s` -//! which support variable output sizes through `VariableOutput` trait. `Update` -//! trait has to be imported as well. +//! This implementation supports run and compile time variable sizes. //! +//! Run time variable output example: //! ```rust -//! use blake2::VarBlake2b; +//! use blake2::Blake2bVar; //! use blake2::digest::{Update, VariableOutput}; +//! use hex_literal::hex; //! -//! let mut hasher = VarBlake2b::new(10).unwrap(); +//! let mut hasher = Blake2bVar::new(10).unwrap(); //! hasher.update(b"my_input"); //! hasher.finalize_variable(|res| { -//! assert_eq!(res, [44, 197, 92, 132, 228, 22, 146, 78, 100, 0]) +//! assert_eq!(res, hex!("2cc55c84e416924e6400")) //! }) //! ``` //! -//! ## Message Authentication Code (MAC) -//! -//! BLAKE2 can be used as a MAC without any additional constructs: -//! +//! Compile time variable output example: //! ```rust -//! use blake2::Blake2b; -//! use blake2::crypto_mac::{Mac, NewMac}; -//! -//! let mut hasher = Blake2b::new_varkey(b"my key").unwrap(); -//! hasher.update(b"hello world"); +//! use blake2::{Blake2b, Digest, digest::consts::U10}; +//! use hex_literal::hex; //! -//! // `result` has type `crypto_mac::Output` which is a thin wrapper around -//! // a byte array and provides a constant time equality check -//! let result = hasher.finalize(); -//! // To get underlying array use the `into_bytes` method, but be careful, -//! // since incorrect use of the code value may permit timing attacks which -//! // defeat the security provided by the `crypto_mac::Output` -//! let code_bytes = result.into_bytes(); +//! type Blake2b80 = Blake2b; //! -//! // To verify the message it's recommended to use `verify` method -//! let mut hasher = Blake2b::new_varkey(b"my key").unwrap(); -//! hasher.update(b"hello world"); -//! // `verify` return `Ok(())` if code is correct, `Err(MacError)` otherwise -//! hasher.verify(&code_bytes).unwrap(); +//! let mut hasher = Blake2b80::new(); +//! hasher.update(b"my_input"); +//! let res = hasher.finalize(); +//! assert_eq!(res[..], hex!("2cc55c84e416924e6400")[..]); //! ``` //! //! # Acknowledgment @@ -83,8 +70,9 @@ #![no_std] #![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_root_url = "https://docs.rs/blake2/0.10.0" )] #![warn(missing_docs, rust_2018_idioms)] #![cfg_attr(feature = "simd", feature(platform_intrinsics, repr_simd))] @@ -94,19 +82,93 @@ #[cfg(feature = "std")] extern crate std; +pub use digest::{self, Digest}; + +use core::{convert::TryInto, fmt, marker::PhantomData, ops::Div}; +use digest::{ + block_buffer::{Lazy, LazyBuffer}, + consts::{U128, U32, U4, U64}, + core_api::{ + AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, + CtVariableCoreWrapper, OutputSizeUser, RtVariableCoreWrapper, UpdateCore, + VariableOutputCore, + }, + crypto_common::{InvalidLength, Key, KeyInit, KeySizeUser}, + generic_array::{ + typenum::{IsLessOrEqual, LeEq, NonZero, Unsigned}, + ArrayLength, GenericArray, + }, + FixedOutput, HashMarker, InvalidOutputSize, MacMarker, Output, Update, +}; + mod as_bytes; mod consts; mod simd; #[macro_use] -mod blake2; +mod macros; -mod blake2b; -mod blake2s; +use as_bytes::AsBytes; +use consts::{BLAKE2B_IV, BLAKE2S_IV}; +use simd::{u32x4, u64x4, Vector4}; -pub use crypto_mac; -pub use digest::{self, Digest}; +blake2_impl!( + Blake2bVarCore, + "Blake2b", + u64, + u64x4, + U64, + U128, + 32, + 24, + 16, + 63, + BLAKE2B_IV, + "Blake2b instance with a variable output.", + "Blake2b instance with a fixed output.", +); + +/// BLAKE2b which allows to choose output size at runtime. +pub type Blake2bVar = RtVariableCoreWrapper; +/// Core hasher state of BLAKE2b generic over output size. +pub type Blake2bCore = CtVariableCoreWrapper; +/// BLAKE2b generic over output size. +pub type Blake2b = CoreWrapper>; +/// BLAKE2b-512 hasher state. +pub type Blake2b512 = Blake2b; + +blake2_mac_impl!(Blake2bMac, Blake2bVarCore, U64, "Blake2b MAC function"); + +/// BLAKE2b-512 MAC state. +pub type Blake2bMac512 = Blake2bMac; + +blake2_impl!( + Blake2sVarCore, + "Blake2s", + u32, + u32x4, + U32, + U64, + 16, + 12, + 8, + 7, + BLAKE2S_IV, + "Blake2s instance with a variable output.", + "Blake2s instance with a fixed output.", +); + +/// BLAKE2s which allows to choose output size at runtime. +pub type Blake2sVar = RtVariableCoreWrapper; +/// Core hasher state of BLAKE2s generic over output size. +pub type Blake2sCore = CtVariableCoreWrapper; +/// BLAKE2s generic over output size. +pub type Blake2s = CoreWrapper>; +/// BLAKE2s-256 hasher state. +pub type Blake2s256 = Blake2s; + +blake2_mac_impl!(Blake2sMac, Blake2sVarCore, U32, "Blake2s MAC function"); -pub use crate::blake2b::{Blake2b, VarBlake2b}; -pub use crate::blake2s::{Blake2s, VarBlake2s}; +/// BLAKE2s-256 MAC state. +pub type Blake2sMac256 = Blake2sMac; diff --git a/blake2/src/macros.rs b/blake2/src/macros.rs new file mode 100644 index 000000000..fd583e7ea --- /dev/null +++ b/blake2/src/macros.rs @@ -0,0 +1,371 @@ +macro_rules! blake2_impl { + ( + $name:ident, $alg_name:expr, $word:ident, $vec:ident, $bytes:ident, + $block_size:ident, $R1:expr, $R2:expr, $R3:expr, $R4:expr, $IV:expr, + $vardoc:expr, $doc:expr, + ) => { + #[derive(Clone)] + #[doc=$vardoc] + pub struct $name { + h: [$vec; 2], + t: u64, + } + + impl $name { + #[inline(always)] + fn iv0() -> $vec { + $vec::new($IV[0], $IV[1], $IV[2], $IV[3]) + } + #[inline(always)] + fn iv1() -> $vec { + $vec::new($IV[4], $IV[5], $IV[6], $IV[7]) + } + + /// Creates a new context with the full set of sequential-mode parameters. + pub fn new_with_params( + salt: &[u8], + persona: &[u8], + key_size: usize, + output_size: usize, + ) -> Self { + assert!(key_size <= $bytes::to_usize()); + assert!(output_size <= $bytes::to_usize()); + + // The number of bytes needed to express two words. + let length = $bytes::to_usize() / 4; + assert!(salt.len() <= length); + assert!(persona.len() <= length); + + // Build a parameter block + let mut p = [0 as $word; 8]; + p[0] = 0x0101_0000 ^ ((key_size as $word) << 8) ^ (output_size as $word); + + // salt is two words long + if salt.len() < length { + let mut padded_salt = + GenericArray::>::Output>::default(); + for i in 0..salt.len() { + padded_salt[i] = salt[i]; + } + p[4] = $word::from_le_bytes(padded_salt[0..length / 2].try_into().unwrap()); + p[5] = $word::from_le_bytes( + padded_salt[length / 2..padded_salt.len()] + .try_into() + .unwrap(), + ); + } else { + p[4] = $word::from_le_bytes(salt[0..salt.len() / 2].try_into().unwrap()); + p[5] = + $word::from_le_bytes(salt[salt.len() / 2..salt.len()].try_into().unwrap()); + } + + // persona is also two words long + if persona.len() < length { + let mut padded_persona = + GenericArray::>::Output>::default(); + for i in 0..persona.len() { + padded_persona[i] = persona[i]; + } + p[6] = $word::from_le_bytes(padded_persona[0..length / 2].try_into().unwrap()); + p[7] = $word::from_le_bytes( + padded_persona[length / 2..padded_persona.len()] + .try_into() + .unwrap(), + ); + } else { + p[6] = $word::from_le_bytes(persona[0..length / 2].try_into().unwrap()); + p[7] = $word::from_le_bytes( + persona[length / 2..persona.len()].try_into().unwrap(), + ); + } + + $name { + h: [ + Self::iv0() ^ $vec::new(p[0], p[1], p[2], p[3]), + Self::iv1() ^ $vec::new(p[4], p[5], p[6], p[7]), + ], + t: 0, + } + } + + fn finalize_with_flag( + &mut self, + final_block: &GenericArray, + flag: $word, + ) -> GenericArray { + self.compress(final_block, !0, flag); + let buf = [self.h[0].to_le(), self.h[1].to_le()]; + GenericArray::clone_from_slice(buf.as_bytes()) + } + + fn compress(&mut self, block: &Block, f0: $word, f1: $word) { + use $crate::consts::SIGMA; + + #[inline(always)] + fn quarter_round(v: &mut [$vec; 4], rd: u32, rb: u32, m: $vec) { + v[0] = v[0].wrapping_add(v[1]).wrapping_add(m.from_le()); + v[3] = (v[3] ^ v[0]).rotate_right_const(rd); + v[2] = v[2].wrapping_add(v[3]); + v[1] = (v[1] ^ v[2]).rotate_right_const(rb); + } + + #[inline(always)] + fn shuffle(v: &mut [$vec; 4]) { + v[1] = v[1].shuffle_left_1(); + v[2] = v[2].shuffle_left_2(); + v[3] = v[3].shuffle_left_3(); + } + + #[inline(always)] + fn unshuffle(v: &mut [$vec; 4]) { + v[1] = v[1].shuffle_right_1(); + v[2] = v[2].shuffle_right_2(); + v[3] = v[3].shuffle_right_3(); + } + + #[inline(always)] + fn round(v: &mut [$vec; 4], m: &[$word; 16], s: &[usize; 16]) { + quarter_round(v, $R1, $R2, $vec::gather(m, s[0], s[2], s[4], s[6])); + quarter_round(v, $R3, $R4, $vec::gather(m, s[1], s[3], s[5], s[7])); + + shuffle(v); + quarter_round(v, $R1, $R2, $vec::gather(m, s[8], s[10], s[12], s[14])); + quarter_round(v, $R3, $R4, $vec::gather(m, s[9], s[11], s[13], s[15])); + unshuffle(v); + } + + let mut m: [$word; 16] = Default::default(); + let n = core::mem::size_of::<$word>(); + for (v, chunk) in m.iter_mut().zip(block.chunks_exact(n)) { + *v = $word::from_le_bytes(chunk.try_into().unwrap()); + } + let h = &mut self.h; + + let t0 = self.t as $word; + let t1 = match $bytes::to_u8() { + 64 => 0, + 32 => (self.t >> 32) as $word, + _ => unreachable!(), + }; + + let mut v = [ + h[0], + h[1], + Self::iv0(), + Self::iv1() ^ $vec::new(t0, t1, f0, f1), + ]; + + round(&mut v, &m, &SIGMA[0]); + round(&mut v, &m, &SIGMA[1]); + round(&mut v, &m, &SIGMA[2]); + round(&mut v, &m, &SIGMA[3]); + round(&mut v, &m, &SIGMA[4]); + round(&mut v, &m, &SIGMA[5]); + round(&mut v, &m, &SIGMA[6]); + round(&mut v, &m, &SIGMA[7]); + round(&mut v, &m, &SIGMA[8]); + round(&mut v, &m, &SIGMA[9]); + if $bytes::to_u8() == 64 { + round(&mut v, &m, &SIGMA[0]); + round(&mut v, &m, &SIGMA[1]); + } + + h[0] = h[0] ^ (v[0] ^ v[2]); + h[1] = h[1] ^ (v[1] ^ v[3]); + } + } + + impl HashMarker for $name {} + + impl BlockSizeUser for $name { + type BlockSize = $block_size; + } + + impl BufferKindUser for $name { + type BufferKind = Lazy; + } + + impl UpdateCore for $name { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + for block in blocks { + self.t += block.len() as u64; + self.compress(block, 0, 0); + } + } + } + + impl VariableOutputCore for $name { + type MaxOutputSize = $bytes; + + #[inline] + fn new(output_size: usize) -> Result { + if output_size > Self::MaxOutputSize::USIZE { + return Err(InvalidOutputSize); + } + Ok(Self::new_with_params(&[], &[], 0, output_size)) + } + + #[inline] + fn finalize_variable_core( + &mut self, + buffer: &mut Buffer, + output_size: usize, + f: impl FnOnce(&[u8]), + ) { + self.t += buffer.get_pos() as u64; + let block = buffer.pad_with_zeros(); + let res = self.finalize_with_flag(block, 0); + f(&res[..output_size]); + } + } + + impl AlgorithmName for $name { + #[inline] + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str($alg_name) + } + } + + impl fmt::Debug for $name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(concat!(stringify!($name), " { ... }")) + } + } + }; +} + +macro_rules! blake2_mac_impl { + ( + $name:ident, $hash:ty, $max_size:ty, $doc:expr + ) => { + #[derive(Clone)] + #[doc=$doc] + pub struct $name + where + OutSize: ArrayLength + IsLessOrEqual<$max_size>, + LeEq: NonZero, + { + core: $hash, + buffer: LazyBuffer<<$hash as BlockSizeUser>::BlockSize>, + _out: PhantomData, + } + + impl $name + where + OutSize: ArrayLength + IsLessOrEqual<$max_size>, + LeEq: NonZero, + { + /// Create new instance using provided key, salt, and persona. + /// + /// Key length should not be bigger than block size, salt and persona + /// length should not be bigger than quarter of block size. If any + /// of those conditions is false the method will return an error. + #[inline] + pub fn new_with_salt_and_personal( + key: &[u8], + salt: &[u8], + persona: &[u8], + ) -> Result { + let kl = key.len(); + let bs = <$hash as BlockSizeUser>::BlockSize::USIZE; + let qbs = bs / 4; + if kl > bs || salt.len() > qbs || persona.len() > qbs { + return Err(InvalidLength); + } + let mut key_block = Block::<$hash>::default(); + key_block[..kl].copy_from_slice(key); + Ok(Self { + core: <$hash>::new_with_params(salt, persona, key.len(), OutSize::USIZE), + buffer: LazyBuffer::new(&key_block), + _out: PhantomData, + }) + } + } + + impl KeySizeUser for $name + where + OutSize: ArrayLength + IsLessOrEqual<$max_size>, + LeEq: NonZero, + { + type KeySize = <$hash as BlockSizeUser>::BlockSize; + } + + impl KeyInit for $name + where + OutSize: ArrayLength + IsLessOrEqual<$max_size>, + LeEq: NonZero, + { + fn new(key: &Key) -> Self { + Self { + core: <$hash>::new_with_params(key, &[], key.len(), OutSize::USIZE), + buffer: LazyBuffer::new(key), + _out: PhantomData, + } + } + + fn new_from_slice(key: &[u8]) -> Result { + let kl = key.len(); + if kl > <$hash as BlockSizeUser>::BlockSize::USIZE { + return Err(InvalidLength); + } + let mut key_block = Block::<$hash>::default(); + key_block[..kl].copy_from_slice(key); + Ok(Self { + core: <$hash>::new_with_params(&[], &[], key.len(), OutSize::USIZE), + buffer: LazyBuffer::new(&key_block), + _out: PhantomData, + }) + } + } + + impl Update for $name + where + OutSize: ArrayLength + IsLessOrEqual<$max_size>, + LeEq: NonZero, + { + #[inline] + fn update(&mut self, input: &[u8]) { + let Self { core, buffer, .. } = self; + buffer.digest_blocks(input, |blocks| core.update_blocks(blocks)); + } + } + + impl OutputSizeUser for $name + where + OutSize: ArrayLength + IsLessOrEqual<$max_size>, + LeEq: NonZero, + { + type OutputSize = OutSize; + } + + impl FixedOutput for $name + where + OutSize: ArrayLength + IsLessOrEqual<$max_size>, + LeEq: NonZero, + { + #[inline] + fn finalize_into(mut self, out: &mut Output) { + let Self { core, buffer, .. } = &mut self; + core.finalize_variable_core(buffer, OutSize::USIZE, |res| out.copy_from_slice(res)); + } + } + + impl MacMarker for $name + where + OutSize: ArrayLength + IsLessOrEqual<$max_size>, + LeEq: NonZero, + { + } + + impl fmt::Debug for $name + where + OutSize: ArrayLength + IsLessOrEqual<$max_size>, + LeEq: NonZero, + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}{} {{ ... }}", stringify!($name), OutSize::USIZE) + } + } + }; +} diff --git a/blake2/tests/data/blake2b/fixed.blb b/blake2/tests/data/blake2b/fixed.blb index 39d419209..c999b74c6 100644 Binary files a/blake2/tests/data/blake2b/fixed.blb and b/blake2/tests/data/blake2b/fixed.blb differ diff --git a/blake2/tests/data/blake2b/mac.blb b/blake2/tests/data/blake2b/mac.blb index 46522340d..eaa6c0395 100644 Binary files a/blake2/tests/data/blake2b/mac.blb and b/blake2/tests/data/blake2b/mac.blb differ diff --git a/blake2/tests/data/blake2b/variable.blb b/blake2/tests/data/blake2b/variable.blb index 5d150c024..24ade82aa 100644 Binary files a/blake2/tests/data/blake2b/variable.blb and b/blake2/tests/data/blake2b/variable.blb differ diff --git a/blake2/tests/data/blake2s/mac.blb b/blake2/tests/data/blake2s/mac.blb index 2c5f3c67c..9b485edfc 100644 Binary files a/blake2/tests/data/blake2s/mac.blb and b/blake2/tests/data/blake2s/mac.blb differ diff --git a/blake2/tests/data/blake2s/variable.blb b/blake2/tests/data/blake2s/variable.blb index 0412b92de..93d4d42ec 100644 Binary files a/blake2/tests/data/blake2s/variable.blb and b/blake2/tests/data/blake2s/variable.blb differ diff --git a/blake2/tests/lib.rs b/blake2/tests/lib.rs index ba42b9ffd..2115af47a 100644 --- a/blake2/tests/lib.rs +++ b/blake2/tests/lib.rs @@ -3,16 +3,21 @@ use digest::dev::{digest_test, variable_test}; use digest::new_test; -new_test!(blake2b_fixed, "blake2b/fixed", blake2::Blake2b, digest_test); +new_test!( + blake2b_fixed, + "blake2b/fixed", + blake2::Blake2b512, + digest_test, +); new_test!( blake2b_variable, "blake2b/variable", - blake2::VarBlake2b, - variable_test + blake2::Blake2bVar, + variable_test, ); new_test!( blake2s_variable, "blake2s/variable", - blake2::VarBlake2s, - variable_test + blake2::Blake2sVar, + variable_test, ); diff --git a/blake2/tests/mac.rs b/blake2/tests/mac.rs index 833c563e3..d57e91de2 100644 --- a/blake2/tests/mac.rs +++ b/blake2/tests/mac.rs @@ -1,6 +1,4 @@ -#![no_std] +use digest::new_mac_test; -use crypto_mac::new_test; - -new_test!(blake2b_mac, "blake2b/mac", blake2::Blake2b); -new_test!(blake2s_mac, "blake2s/mac", blake2::Blake2s); +new_mac_test!(blake2b_mac, "blake2b/mac", blake2::Blake2bMac512); +new_mac_test!(blake2s_mac, "blake2s/mac", blake2::Blake2sMac256); diff --git a/blake2/tests/persona.rs b/blake2/tests/persona.rs index 4defcc801..49e6574e9 100644 --- a/blake2/tests/persona.rs +++ b/blake2/tests/persona.rs @@ -1,23 +1,40 @@ -use blake2::{Blake2b, Blake2s, Digest}; +use blake2::{digest::FixedOutput, Blake2bMac512, Blake2sMac256}; use hex_literal::hex; #[test] +#[rustfmt::skip] fn blake2s_persona() { - let key_bytes = hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"); - let persona = "personal"; - let persona_bytes = persona.as_bytes(); - let ctx = Blake2s::with_params(&key_bytes, &[], persona_bytes); + let key= hex!(" + 000102030405060708090a0b0c0d0e0f + 101112131415161718191a1b1c1d1e1f + "); + let persona = b"personal"; + let ctx = Blake2sMac256::new_with_salt_and_personal(&key, &[], persona).unwrap(); assert_eq!( - ctx.finalize().as_slice(), - &hex!("25a4ee63b594aed3f88a971e1877ef7099534f9097291f88fb86c79b5e70d022")[..] + ctx.finalize_fixed()[..], + hex!(" + 25a4ee63b594aed3f88a971e1877ef70 + 99534f9097291f88fb86c79b5e70d022 + ")[..], ); } #[test] +#[rustfmt::skip] fn blake2b_persona() { - let key_bytes = hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"); - let persona = "personal"; - let persona_bytes = persona.as_bytes(); - let ctx = Blake2b::with_params(&key_bytes, &[], persona_bytes); - assert_eq!(ctx.finalize().as_slice(), &hex!("03de3b295dcfc3b25b05abb09bc95fe3e9ff3073638badc68101d1e42019d0771dd07525a3aae8318e92c5e5d967ba92e4810d0021d7bf3b49da0b4b4a8a4e1f")[..]); + let key = hex!(" + 000102030405060708090a0b0c0d0e0f + 101112131415161718191a1b1c1d1e1f + "); + let persona = b"personal"; + let ctx = Blake2bMac512::new_with_salt_and_personal(&key, &[], persona).unwrap(); + assert_eq!( + ctx.finalize_fixed()[..], + hex!(" + 03de3b295dcfc3b25b05abb09bc95fe3 + e9ff3073638badc68101d1e42019d077 + 1dd07525a3aae8318e92c5e5d967ba92 + e4810d0021d7bf3b49da0b4b4a8a4e1f + ")[..], + ); } diff --git a/fsb/CHANGELOG.md b/fsb/CHANGELOG.md index bea8879e4..7d75d02e9 100644 --- a/fsb/CHANGELOG.md +++ b/fsb/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## 0.1.0 (2021-11-22) +### Changed +- Update to `digest` v0.10 ([#217]) + +[#217]: https://github.com/RustCrypto/hashes/pull/217 + ## 0.0.2 (2020-07-21) - Fixed `Reset` implementation bug. Reduce crate size by using binary dump of `PI` ([#300]) diff --git a/fsb/Cargo.toml b/fsb/Cargo.toml index 9eb9fd6fd..96ffe6042 100644 --- a/fsb/Cargo.toml +++ b/fsb/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "fsb" description = "FSB hash function" -version = "0.0.2" +version = "0.1.0" # Also update html_root_url in lib.rs when bumping this authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" readme = "README.md" @@ -11,15 +11,13 @@ keywords = ["crypto", "fsb", "hash", "digest"] categories = ["cryptography", "no-std"] [dependencies] -whirlpool = { version = "0.9", path = "../whirlpool", default-features = false } -digest = "0.9" -block-buffer = { version = "0.9", features = ["block-padding"] } -opaque-debug = "0.3" +digest = "0.10" +whirlpool = { version = "0.10", path = "../whirlpool", default-features = false } [dev-dependencies] +digest = { version = "0.10", features = ["dev"] } hex-literal = "0.2" -digest = { version = "0.9", features = ["dev"] } [features] -asm = ["whirlpool/asm"] -std = ["whirlpool/std"] +default = ["std"] +std = ["digest/std"] diff --git a/ripemd160/LICENSE-APACHE b/fsb/LICENSE-APACHE similarity index 100% rename from ripemd160/LICENSE-APACHE rename to fsb/LICENSE-APACHE diff --git a/ripemd160/LICENSE-MIT b/fsb/LICENSE-MIT similarity index 89% rename from ripemd160/LICENSE-MIT rename to fsb/LICENSE-MIT index 66cf75563..c869ada57 100644 --- a/ripemd160/LICENSE-MIT +++ b/fsb/LICENSE-MIT @@ -1,6 +1,4 @@ -Copyright (c) 2006-2009 Graydon Hoare -Copyright (c) 2009-2013 Mozilla Foundation -Copyright (c) 2016 Artyom Pavlov +Copyright (c) 2021 The RustCrypto Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/fsb/README.md b/fsb/README.md index 53319e926..bff04069c 100644 --- a/fsb/README.md +++ b/fsb/README.md @@ -13,7 +13,7 @@ Pure Rust implementation of the [FSB hash function][1] family. ## Minimum Supported Rust Version -Rust **1.47** or higher. +Rust **1.41** or higher. Minimum supported Rust version can be changed in the future, but it will be done with a minor version bump. diff --git a/fsb/benches/fsb160.rs b/fsb/benches/fsb160.rs new file mode 100644 index 000000000..8294f9d22 --- /dev/null +++ b/fsb/benches/fsb160.rs @@ -0,0 +1,4 @@ +#![no_std] +#![feature(test)] + +digest::bench!(fsb::Fsb160); diff --git a/fsb/benches/fsb224.rs b/fsb/benches/fsb224.rs new file mode 100644 index 000000000..b8c65dbae --- /dev/null +++ b/fsb/benches/fsb224.rs @@ -0,0 +1,4 @@ +#![no_std] +#![feature(test)] + +digest::bench!(fsb::Fsb224); diff --git a/fsb/benches/fsb256.rs b/fsb/benches/fsb256.rs new file mode 100644 index 000000000..7a2f33bc4 --- /dev/null +++ b/fsb/benches/fsb256.rs @@ -0,0 +1,4 @@ +#![no_std] +#![feature(test)] + +digest::bench!(fsb::Fsb256); diff --git a/fsb/benches/fsb384.rs b/fsb/benches/fsb384.rs new file mode 100644 index 000000000..a241d1151 --- /dev/null +++ b/fsb/benches/fsb384.rs @@ -0,0 +1,4 @@ +#![no_std] +#![feature(test)] + +digest::bench!(fsb::Fsb384); diff --git a/fsb/benches/fsb512.rs b/fsb/benches/fsb512.rs new file mode 100644 index 000000000..1cfd5f2c4 --- /dev/null +++ b/fsb/benches/fsb512.rs @@ -0,0 +1,4 @@ +#![no_std] +#![feature(test)] + +digest::bench!(fsb::Fsb512); diff --git a/fsb/src/lib.rs b/fsb/src/lib.rs index a8b69eabd..619f2df0d 100644 --- a/fsb/src/lib.rs +++ b/fsb/src/lib.rs @@ -39,38 +39,36 @@ #![no_std] #![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_root_url = "https://docs.rs/fsb/0.1.0" )] -#![deny(unsafe_code)] #![warn(missing_docs, rust_2018_idioms)] #![allow(non_snake_case)] -extern crate alloc; - -#[cfg(feature = "std")] -extern crate std; - -use alloc::vec; - #[macro_use] mod macros; +use core::fmt; pub use digest::{self, Digest}; -use whirlpool::Whirlpool; - -use core::convert::TryInto; // Double check this contains all values in the reference implementation static PI: &[u8; 272384] = include_bytes!("pi.bin"); -use block_buffer::BlockBuffer; -use digest::generic_array::GenericArray; -use digest::{BlockInput, FixedOutputDirty, Reset, Update}; +use digest::{ + block_buffer::Eager, + core_api::{ + AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore, + OutputSizeUser, Reset, UpdateCore, + }, + generic_array::{typenum::Unsigned, GenericArray}, + HashMarker, Output, +}; // FSB-160 fsb_impl!( Fsb160, + Fsb160Core, 160, U60, U20, @@ -79,12 +77,14 @@ fsb_impl!( 640, 653, 1120, - "FSB-160 hash function." + "FSB-160 hasher state", + "Core FSB-160 hasher state", ); // FSB-224 fsb_impl!( Fsb224, + Fsb224Core, 224, U84, U28, @@ -93,12 +93,14 @@ fsb_impl!( 896, 907, 1568, - "FSB-224 hash function." + "FSB-224 hasher state", + "Core FSB-224 hasher state", ); // FSB-256 fsb_impl!( Fsb256, + Fsb256Core, 256, U96, U32, @@ -107,12 +109,14 @@ fsb_impl!( 1024, 1061, 1792, - "FSB-256 hash function." + "FSB-256 hasher state", + "Core FSB-256 hasher state", ); // FSB-384 fsb_impl!( Fsb384, + Fsb384Core, 384, U115, U48, @@ -121,12 +125,14 @@ fsb_impl!( 1472, 1483, 2392, - "FSB-384 hash function." + "FSB-384 hasher state", + "Core FSB-384 hasher state", ); // FSB-512 fsb_impl!( Fsb512, + Fsb512Core, 512, U155, U64, @@ -135,5 +141,6 @@ fsb_impl!( 1984, 1987, 3224, - "FSB-512 hash function." + "FSB-512 hasher state", + "Core FSB-512 hasher state", ); diff --git a/fsb/src/macros.rs b/fsb/src/macros.rs index 8400722a4..620cb6d2b 100644 --- a/fsb/src/macros.rs +++ b/fsb/src/macros.rs @@ -1,57 +1,94 @@ macro_rules! fsb_impl { ( - $state:ident, $state_num:expr, $blocksize:ident, $outputsize:ident, $n:expr, $w:expr, - $r:expr, $p:expr, $s:expr, $doc:expr + $full_state:ident, $state:ident, $state_num:expr, $blocksize:ident, $outputsize:ident, $n:expr, $w:expr, + $r:expr, $p:expr, $s:expr, $full_doc:expr, $doc:expr, ) => { use digest::consts::{$blocksize, $outputsize}; #[derive(Clone)] #[doc=$doc] pub struct $state { - /// bit size of the message till the current moment (the bit size is represented by a 64 bit - /// number) - bit_length: u64, - /// size of the message being processed - buffer: BlockBuffer<$blocksize>, - /// value of the input vector - hash: [u8; $r / 8], + blocks_len: u64, + state: [u8; $r / 8], } + impl HashMarker for $state {} + + impl BlockSizeUser for $state { + type BlockSize = $blocksize; + } + + impl OutputSizeUser for $state { + type OutputSize = $outputsize; + } + + impl BufferKindUser for $state { + type BufferKind = Eager; + } + + impl UpdateCore for $state { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + self.blocks_len += blocks.len() as u64; + for block in blocks { + Self::compress(&mut self.state, Self::convert(block)); + } + } + } + + impl FixedOutputCore for $state { + #[inline] + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + let block_bytes = self.blocks_len * Self::BlockSize::U64; + let bit_len = 8 * (block_bytes + buffer.get_pos() as u64); + let mut h = self.state; + buffer.len64_padding_be(bit_len, |b| Self::compress(&mut h, Self::convert(b))); + + let res = whirlpool::Whirlpool::digest(&h[..]); + let n = out.len(); + out.copy_from_slice(&res[..n]); + } + } + + impl Default for $state { + #[inline] + fn default() -> Self { + Self { + blocks_len: 0u64, + state: [0u8; $r / 8], + } + } + } + + impl Reset for $state { + #[inline] + fn reset(&mut self) { + *self = Default::default(); + } + } + + impl AlgorithmName for $state { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(stringify!($full_state)) + } + } + + impl fmt::Debug for $state { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(concat!(stringify!($state), " { ... }")) + } + } + + #[doc=$full_doc] + pub type $full_state = CoreWrapper<$state>; + impl $state { - // constants const SIZE_OUTPUT_COMPRESS: usize = $r / 8; const SIZE_INPUT_COMPRESS: usize = $s / 8; - const HASH_OUTPUT_SIZE: usize = $state_num / 8; const SIZE_MSG_CHUNKS: usize = Self::SIZE_INPUT_COMPRESS - Self::SIZE_OUTPUT_COMPRESS; const SIZE_VECTORS: usize = $p / 8 + 1; const SHIFT: u8 = 8 - ($p % 8) as u8; - fn update_len(&mut self, len: u64) { - self.bit_length += len * 8; - } - - fn finalize_inner(&mut self) { - let hash = &mut self.hash; - let pos = self.buffer.position(); - if pos < Self::SIZE_MSG_CHUNKS - 8 { - let mut padding = vec![0; Self::SIZE_MSG_CHUNKS - pos - 8]; - padding[0] = 128u8; - padding.extend_from_slice(&Self::helper_transform_usize(self.bit_length)); - self.buffer - .input_block(&padding, |b| Self::compress(hash, Self::convert(b))); - } else { - let mut padding = vec![0; Self::SIZE_MSG_CHUNKS - pos]; - padding[0] = 128u8; - self.buffer - .input_block(&padding, |b| Self::compress(hash, Self::convert(b))); - let mut second_padding = vec![0; Self::SIZE_MSG_CHUNKS - 8]; - second_padding - .extend_from_slice(&Self::helper_transform_usize(self.bit_length)); - self.buffer - .input_block(&second_padding, |b| Self::compress(hash, Self::convert(b))); - } - } - fn define_iv(index: usize) -> [u8; Self::SIZE_VECTORS] { let mut subset_pi: [u8; Self::SIZE_VECTORS] = [0u8; Self::SIZE_VECTORS]; subset_pi.copy_from_slice( @@ -72,21 +109,21 @@ macro_rules! fsb_impl { /// $(W_i)_{i\in[0;w-1]}$ between $0$ and $n - 1$. The value of each $W_i$ is computed /// from the inputs bits like this: /// $W_i = i \times (n / w) + IV_i + M_i \times 2^{r / w}. - fn computing_W_indices( + fn computing_w_indices( input_vector: &[u8; Self::SIZE_OUTPUT_COMPRESS], message: &[u8; Self::SIZE_MSG_CHUNKS], ) -> [u32; $w] { - let mut W_indices: [u32; $w] = [0; $w]; + let mut wind: [u32; $w] = [0; $w]; let divided_message: [u8; $w] = Self::dividing_bits(message, ($s - $r) / $w); for i in 0..($w) { let message_i = divided_message[i] as u32; - W_indices[i] = (i * $n / $w) as u32 + wind[i] = (i * $n / $w) as u32 + input_vector[i] as u32 + (message_i << ($r / $w) as u8); } - W_indices + wind } /// This function servers the purpose presented in table 3, of breaking a bit array into @@ -133,7 +170,7 @@ macro_rules! fsb_impl { ) { let mut initial_vector = [0u8; Self::SIZE_OUTPUT_COMPRESS]; - let w_indices = Self::computing_W_indices(hash, message_block); + let w_indices = Self::computing_w_indices(hash, message_block); for w_index in w_indices.iter() { let chosen_vec = w_index / $r as u32; let shift_value = w_index % $r as u32; @@ -149,18 +186,6 @@ macro_rules! fsb_impl { *hash = initial_vector; } - fn final_compression( - initial_vector: [u8; Self::SIZE_OUTPUT_COMPRESS], - ) -> [u8; Self::HASH_OUTPUT_SIZE] { - // Now we use Whirpool - let mut result = [0u8; Self::HASH_OUTPUT_SIZE]; - let mut hasher = Whirlpool::new(); - - Update::update(&mut hasher, &initial_vector); - result.copy_from_slice(&hasher.finalize()[..Self::HASH_OUTPUT_SIZE]); - result - } - fn shift_and_truncate( array: &mut [u8; Self::SIZE_VECTORS], shift_value: u32, @@ -170,9 +195,7 @@ macro_rules! fsb_impl { let mut truncated = [0u8; Self::SIZE_OUTPUT_COMPRESS]; if shift_value == 0 { - array[..Self::SIZE_OUTPUT_COMPRESS] - .try_into() - .expect("SIZE_VECTORS is always bigger than SIZE_OUTPUT_COMPRESS") + truncated.copy_from_slice(&array[..Self::SIZE_OUTPUT_COMPRESS]); } else if shift_value <= (bits_in_cue as u32) { let bytes_to_shift = 1; let starting_byte = (array_len - bytes_to_shift) as usize; @@ -183,8 +206,6 @@ macro_rules! fsb_impl { truncated[position] ^= array[position - 1] >> (8 - shift_value); truncated[position] ^= array[position] << shift_value; } - - truncated } else { // First we need to decide which is the last byte and bit that will go to the first position. // Then, we build our truncated array from there. Recall that the last byte is not complete, @@ -246,8 +267,6 @@ macro_rules! fsb_impl { } } } - - truncated } else { truncated[..bytes_to_shift].clone_from_slice( &array[starting_byte..(starting_byte + bytes_to_shift)], @@ -261,76 +280,14 @@ macro_rules! fsb_impl { truncated[position] ^= array[index] << (8 - bits_in_cue); truncated[position] ^= array[index + 1] >> bits_in_cue; } - truncated } } - } - - // I'm trying to avoid use unsafe code for this transformation. We are certain that the bit - // size of the buffer can be represented in 8 bytes. - fn helper_transform_usize(x: u64) -> [u8; 8] { - let b1: u8 = ((x >> 56) & 0xff) as u8; - let b2: u8 = ((x >> 48) & 0xff) as u8; - let b3: u8 = ((x >> 40) & 0xff) as u8; - let b4: u8 = ((x >> 32) & 0xff) as u8; - let b5: u8 = ((x >> 24) & 0xff) as u8; - let b6: u8 = ((x >> 16) & 0xff) as u8; - let b7: u8 = ((x >> 8) & 0xff) as u8; - let b8: u8 = (x & 0xff) as u8; - [b1, b2, b3, b4, b5, b6, b7, b8] + truncated } fn convert(block: &GenericArray) -> &[u8; Self::SIZE_MSG_CHUNKS] { - #[allow(unsafe_code)] - unsafe { - &*(block.as_ptr() as *const [u8; Self::SIZE_MSG_CHUNKS]) - } - } - } - - impl Default for $state { - fn default() -> Self { - Self { - bit_length: 0u64, - buffer: BlockBuffer::default(), - hash: [0u8; $r / 8], - } - } - } - - impl BlockInput for $state { - type BlockSize = $blocksize; - } - - impl Update for $state { - fn update(&mut self, input: impl AsRef<[u8]>) { - let input = input.as_ref(); - self.update_len(input.len() as u64); - - let hash = &mut self.hash; - self.buffer - .input_block(input, |b| $state::compress(hash, $state::convert(b))); - } - } - - impl FixedOutputDirty for $state { - type OutputSize = $outputsize; - - fn finalize_into_dirty(&mut self, out: &mut GenericArray) { - self.finalize_inner(); - let final_whirpool = $state::final_compression(self.hash); - out.copy_from_slice(&final_whirpool) - } - } - - impl Reset for $state { - fn reset(&mut self) { - self.buffer.reset(); - self.hash = [0u8; $r / 8]; - self.bit_length = 0; + unsafe { &*(block.as_ptr() as *const [u8; Self::SIZE_MSG_CHUNKS]) } } } - opaque_debug::implement!($state); - digest::impl_write!($state); }; } diff --git a/fsb/tests/data/fsb160.blb b/fsb/tests/data/fsb160.blb index deecdfec3..7ea2346e7 100644 Binary files a/fsb/tests/data/fsb160.blb and b/fsb/tests/data/fsb160.blb differ diff --git a/fsb/tests/data/fsb224.blb b/fsb/tests/data/fsb224.blb index 57ca2febc..9a476c723 100644 Binary files a/fsb/tests/data/fsb224.blb and b/fsb/tests/data/fsb224.blb differ diff --git a/fsb/tests/data/fsb256.blb b/fsb/tests/data/fsb256.blb index 0caef2731..6e3e4672a 100644 Binary files a/fsb/tests/data/fsb256.blb and b/fsb/tests/data/fsb256.blb differ diff --git a/fsb/tests/data/fsb384.blb b/fsb/tests/data/fsb384.blb index 65cc572e6..60ce430d1 100644 Binary files a/fsb/tests/data/fsb384.blb and b/fsb/tests/data/fsb384.blb differ diff --git a/fsb/tests/data/fsb512.blb b/fsb/tests/data/fsb512.blb index fa6c7b3d9..f20de348a 100644 Binary files a/fsb/tests/data/fsb512.blb and b/fsb/tests/data/fsb512.blb differ diff --git a/gost94/CHANGELOG.md b/gost94/CHANGELOG.md index 120bd45e7..a1a2c97c6 100644 --- a/gost94/CHANGELOG.md +++ b/gost94/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## 0.10.0 (2021-11-22) +### Changed +- Update to `digest` v0.10 ([#217]) + +[#217]: https://github.com/RustCrypto/hashes/pull/217 + ## 0.9.1 (2020-11-03) ### Fixed - Arithmetic overflow bug. ([#193]) diff --git a/gost94/Cargo.toml b/gost94/Cargo.toml index 9de6ffbfb..057e92a04 100644 --- a/gost94/Cargo.toml +++ b/gost94/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gost94" -version = "0.9.1" +version = "0.10.0" # Also update html_root_url in lib.rs when bumping this description = "GOST R 34.11-94 hash function" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -12,12 +12,10 @@ keywords = ["crypto", "gost94", "gost", "hash", "digest"] categories = ["cryptography", "no-std"] [dependencies] -digest = "0.9" -block-buffer = { version = "0.9", features = ["block-padding"] } -opaque-debug = "0.3" +digest = "0.10" [dev-dependencies] -digest = { version = "0.9", features = ["dev"] } +digest = { version = "0.10", features = ["dev"] } hex-literal = "0.2" [features] diff --git a/gost94/examples/gost94_cryptopro_sum.rs b/gost94/examples/gost94_cryptopro_sum.rs deleted file mode 100644 index c6bee4d74..000000000 --- a/gost94/examples/gost94_cryptopro_sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use gost94::{Digest, Gost94CryptoPro}; -use std::env; -use std::fs; -use std::io::{self, Read}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = D::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/gost94/examples/gost94_test_sum.rs b/gost94/examples/gost94_test_sum.rs deleted file mode 100644 index 8f31b1906..000000000 --- a/gost94/examples/gost94_test_sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use gost94::{Digest, Gost94Test}; -use std::env; -use std::fs; -use std::io::{self, Read}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = D::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/gost94/src/cryptopro.rs b/gost94/src/cryptopro.rs deleted file mode 100644 index e290472ca..000000000 --- a/gost94/src/cryptopro.rs +++ /dev/null @@ -1,12 +0,0 @@ -const S_CRYPTO_PRO: SBox = [ - [10, 4, 5, 6, 8, 1, 3, 7, 13, 12, 14, 0, 9, 2, 11, 15], - [5, 15, 4, 0, 2, 13, 11, 9, 1, 7, 6, 3, 12, 14, 10, 8], - [7, 15, 12, 14, 9, 4, 1, 0, 3, 11, 5, 2, 6, 10, 8, 13], - [4, 10, 7, 12, 0, 15, 2, 8, 14, 1, 6, 5, 13, 11, 9, 3], - [7, 6, 4, 11, 9, 12, 2, 10, 1, 8, 0, 14, 15, 13, 3, 5], - [7, 6, 2, 4, 13, 9, 15, 0, 10, 1, 5, 11, 8, 14, 12, 3], - [13, 14, 4, 1, 7, 0, 5, 10, 3, 12, 8, 15, 6, 2, 9, 11], - [1, 3, 10, 9, 5, 11, 4, 15, 8, 6, 7, 14, 13, 0, 2, 12], -]; - -gost94_impl!(Gost94CryptoPro, S_CRYPTO_PRO); diff --git a/gost94/src/gost94.rs b/gost94/src/gost94_core.rs similarity index 63% rename from gost94/src/gost94.rs rename to gost94/src/gost94_core.rs index 8bbb0fe5a..569789a0b 100644 --- a/gost94/src/gost94.rs +++ b/gost94/src/gost94_core.rs @@ -1,19 +1,23 @@ #![allow(clippy::many_single_char_names)] -use block_buffer::block_padding::ZeroPadding; -use block_buffer::BlockBuffer; -use core::convert::TryInto; -use digest::{consts::U32, generic_array::GenericArray}; -use digest::{BlockInput, FixedOutputDirty, Reset, Update}; - -pub(crate) type Block = [u8; 32]; +use core::{convert::TryInto, fmt}; +use digest::{ + block_buffer::Eager, + consts::U32, + core_api::{ + AlgorithmName, Block as TBlock, BlockSizeUser, Buffer, BufferKindUser, FixedOutputCore, + OutputSizeUser, Reset, UpdateCore, + }, + generic_array::{typenum::Unsigned, GenericArray}, + HashMarker, Output, +}; + +use crate::params::{Block, Gost94Params, SBox}; const C: Block = [ 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, ]; -pub type SBox = [[u8; 16]; 8]; - fn sbox(a: u32, s: &SBox) -> u32 { let mut v = 0; @@ -114,15 +118,23 @@ fn psi(block: &mut Block) { block.copy_from_slice(&out); } +#[inline(always)] +fn adc(a: &mut u64, b: u64, carry: &mut u64) { + let ret = (*a as u128) + (b as u128) + (*carry as u128); + *a = ret as u64; + *carry = (ret >> 64) as u64; +} + +/// Core GOST94 algorithm generic over parameters. #[derive(Clone)] -struct Gost94State { - s: SBox, +pub struct Gost94Core { h: Block, n: [u64; 4], sigma: [u64; 4], + _m: core::marker::PhantomData

, } -impl Gost94State { +impl Gost94Core

{ fn shuffle(&mut self, m: &Block, s: &Block) { let mut res = Block::default(); res.copy_from_slice(s); @@ -141,23 +153,23 @@ impl Gost94State { let mut s = Block::default(); s.copy_from_slice(&self.h); let k = p(x(&self.h, m)); - encrypt(&mut s[0..8], k, &self.s); + encrypt(&mut s[0..8], k, &P::S_BOX); let u = a(self.h); let v = a(a(*m)); let k = p(x(&u, &v)); - encrypt(&mut s[8..16], k, &self.s); + encrypt(&mut s[8..16], k, &P::S_BOX); let mut u = a(u); x_mut(&mut u, &C); let v = a(a(v)); let k = p(x(&u, &v)); - encrypt(&mut s[16..24], k, &self.s); + encrypt(&mut s[16..24], k, &P::S_BOX); let u = a(u); let v = a(a(v)); let k = p(x(&u, &v)); - encrypt(&mut s[24..32], k, &self.s); + encrypt(&mut s[24..32], k, &P::S_BOX); self.shuffle(m, &s); } @@ -178,92 +190,88 @@ impl Gost94State { adc(&mut self.n[3], 0, &mut carry); } - fn process_block(&mut self, block: &GenericArray) { + #[inline(always)] + fn compress(&mut self, block: &GenericArray) { let block = unsafe { &*(block.as_ptr() as *const [u8; 32]) }; self.f(block); self.update_sigma(block); } } -/// GOST94 -#[derive(Clone)] -pub struct Gost94 { - buffer: BlockBuffer, - state: Gost94State, - h0: Block, -} - -impl Gost94 { - /// Create new [`Gost94`] instance with given S-Box and IV - pub fn new(s: SBox, h: Block) -> Self { - let n = Default::default(); - let sigma = Default::default(); - Gost94 { - buffer: Default::default(), - h0: h, - state: Gost94State { s, h, n, sigma }, - } - } -} +impl HashMarker for Gost94Core

{} -impl BlockInput for Gost94 { +impl BlockSizeUser for Gost94Core

{ type BlockSize = U32; } -impl Update for Gost94 { - fn update(&mut self, input: impl AsRef<[u8]>) { - let input = input.as_ref(); - let s = &mut self.state; - s.update_n(input.len()); - self.buffer.input_block(input, |d| s.process_block(d)); - } +impl BufferKindUser for Gost94Core

{ + type BufferKind = Eager; } -impl FixedOutputDirty for Gost94 { +impl OutputSizeUser for Gost94Core

{ type OutputSize = U32; +} - fn finalize_into_dirty(&mut self, out: &mut GenericArray) { - let self_state = &mut self.state; - - if self.buffer.position() != 0 { - let block = self - .buffer - .pad_with::() - .expect("we never use input_lazy"); +impl UpdateCore for Gost94Core

{ + #[inline] + fn update_blocks(&mut self, blocks: &[TBlock]) { + let len = Self::BlockSize::USIZE * blocks.len(); + self.update_n(len); + blocks.iter().for_each(|b| self.compress(b)); + } +} - self_state.process_block(block); +impl FixedOutputCore for Gost94Core

{ + #[inline] + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + if buffer.get_pos() != 0 { + self.update_n(buffer.get_pos()); + self.compress(buffer.pad_with_zeros()); } let mut buf = Block::default(); - for (o, v) in buf.chunks_exact_mut(8).zip(self_state.n.iter()) { + for (o, v) in buf.chunks_exact_mut(8).zip(self.n.iter()) { o.copy_from_slice(&v.to_le_bytes()); } - self_state.f(&buf); + self.f(&buf); - for (o, v) in buf.chunks_exact_mut(8).zip(self_state.sigma.iter()) { + for (o, v) in buf.chunks_exact_mut(8).zip(self.sigma.iter()) { o.copy_from_slice(&v.to_le_bytes()); } - self_state.f(&buf); + self.f(&buf); - out.copy_from_slice(&self.state.h); + out.copy_from_slice(&self.h); + } +} + +impl Default for Gost94Core

{ + #[inline] + fn default() -> Self { + Self { + h: P::H0, + n: Default::default(), + sigma: Default::default(), + _m: Default::default(), + } } } -impl Reset for Gost94 { +impl Reset for Gost94Core

{ + #[inline] fn reset(&mut self) { - self.buffer.reset(); - self.state.n = Default::default(); - self.state.h = self.h0; - self.state.sigma = Default::default(); + *self = Default::default(); } } -#[inline(always)] -fn adc(a: &mut u64, b: u64, carry: &mut u64) { - let ret = (*a as u128) + (b as u128) + (*carry as u128); - *a = ret as u64; - *carry = (ret >> 64) as u64; +impl AlgorithmName for Gost94Core

{ + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(P::NAME) + } } -opaque_debug::implement!(Gost94); -digest::impl_write!(Gost94); +impl fmt::Debug for Gost94Core

{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.write_str(P::NAME)?; + f.write_str("Core { .. }") + } +} diff --git a/gost94/src/lib.rs b/gost94/src/lib.rs index 7754c3c49..8427b2c55 100644 --- a/gost94/src/lib.rs +++ b/gost94/src/lib.rs @@ -1,22 +1,21 @@ //! An implementation of the [GOST R 34.11-94][1] cryptographic hash algorithm. //! //! # Usage -//! //! ```rust -//! use gost94::{Gost94Test, Digest}; +//! use gost94::{Gost94CryptoPro, Digest}; //! use hex_literal::hex; //! -//! // create a Gost94 hasher instance with test S-box -//! let mut hasher = Gost94Test::new(); +//! // create Gost94 hasher instance with CryptoPro params +//! let mut hasher = Gost94CryptoPro::new(); //! //! // process input message -//! hasher.update(b"hello world"); +//! hasher.update("The quick brown fox jumps over the lazy dog"); //! //! // acquire hash digest in the form of GenericArray, //! // which in this case is equivalent to [u8; 32] //! let result = hasher.finalize(); //! assert_eq!(result[..], hex!(" -//! 1bb6ce69d2e895a78489c87a0712a2f40258d1fae3a4666c23f8f487bef0e22a +//! 9004294a361a508c586fe53d1f1b02746765e71b765472786e4770d565830a76 //! ")); //! ``` //! @@ -27,25 +26,28 @@ #![no_std] #![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_root_url = "https://docs.rs/gost94/0.10.0" )] #![warn(missing_docs, rust_2018_idioms)] #[cfg(feature = "std")] extern crate std; -#[macro_use] -mod macros; +use digest::core_api::CoreWrapper; -mod cryptopro; -mod gost94; -mod s2015; -mod test_param; +mod gost94_core; +/// GOST94 parameters. +pub mod params; pub use digest::{self, Digest}; -pub use crate::cryptopro::Gost94CryptoPro; -pub use crate::gost94::Gost94; -pub use crate::s2015::Gost94s2015; -pub use crate::test_param::Gost94Test; +pub use gost94_core::Gost94Core; + +/// GOST94 hash function with CryptoPro parameters. +pub type Gost94CryptoPro = CoreWrapper>; +/// GOST94 hash function with S-box defined in GOST R 34.12-2015. +pub type Gost94s2015 = CoreWrapper>; +/// GOST94 hash function with test parameters. +pub type Gost94Test = CoreWrapper>; diff --git a/gost94/src/macros.rs b/gost94/src/macros.rs deleted file mode 100644 index cd78628e7..000000000 --- a/gost94/src/macros.rs +++ /dev/null @@ -1,48 +0,0 @@ -macro_rules! gost94_impl { - ($state:ident, $sbox:expr) => { - use digest::{consts::U32, BlockInput, FixedOutputDirty, Reset, Update}; - use $crate::gost94::{Block, Gost94, SBox}; - - /// GOST94 state - #[derive(Clone)] - pub struct $state { - sh: Gost94, - } - - impl Default for $state { - fn default() -> Self { - $state { - sh: Gost94::new($sbox, Block::default()), - } - } - } - - impl BlockInput for $state { - type BlockSize = U32; - } - - impl Update for $state { - fn update(&mut self, input: impl AsRef<[u8]>) { - let input = input.as_ref(); - self.sh.update(input); - } - } - - impl FixedOutputDirty for $state { - type OutputSize = U32; - - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - self.sh.finalize_into_dirty(out) - } - } - - impl Reset for $state { - fn reset(&mut self) { - self.sh.reset() - } - } - - opaque_debug::implement!($state); - digest::impl_write!($state); - }; -} diff --git a/gost94/src/params.rs b/gost94/src/params.rs new file mode 100644 index 000000000..c7bf9459a --- /dev/null +++ b/gost94/src/params.rs @@ -0,0 +1,70 @@ +pub(crate) type Block = [u8; 32]; +pub(crate) type SBox = [[u8; 16]; 8]; + +/// Trait for storing parameter constants. +// TODO: replace with const generics +pub trait Gost94Params { + /// S-box value. + const S_BOX: SBox; + /// Initialization vector value. + const H0: Block; + /// Algorithm name + const NAME: &'static str; +} + +/// CryptoPro parameters. +#[derive(Copy, Clone, Default)] +pub struct CryptoProParam; + +impl Gost94Params for CryptoProParam { + const S_BOX: SBox = [ + [10, 4, 5, 6, 8, 1, 3, 7, 13, 12, 14, 0, 9, 2, 11, 15], + [5, 15, 4, 0, 2, 13, 11, 9, 1, 7, 6, 3, 12, 14, 10, 8], + [7, 15, 12, 14, 9, 4, 1, 0, 3, 11, 5, 2, 6, 10, 8, 13], + [4, 10, 7, 12, 0, 15, 2, 8, 14, 1, 6, 5, 13, 11, 9, 3], + [7, 6, 4, 11, 9, 12, 2, 10, 1, 8, 0, 14, 15, 13, 3, 5], + [7, 6, 2, 4, 13, 9, 15, 0, 10, 1, 5, 11, 8, 14, 12, 3], + [13, 14, 4, 1, 7, 0, 5, 10, 3, 12, 8, 15, 6, 2, 9, 11], + [1, 3, 10, 9, 5, 11, 4, 15, 8, 6, 7, 14, 13, 0, 2, 12], + ]; + const H0: Block = [0; 32]; + const NAME: &'static str = "Gost94CryptoPro"; +} + +/// S-Box defined in GOST R 34.12-2015. +#[derive(Copy, Clone, Default)] +pub struct S2015Param; + +impl Gost94Params for S2015Param { + const S_BOX: SBox = [ + [12, 4, 6, 2, 10, 5, 11, 9, 14, 8, 13, 7, 0, 3, 15, 1], + [6, 8, 2, 3, 9, 10, 5, 12, 1, 14, 4, 7, 11, 13, 0, 15], + [11, 3, 5, 8, 2, 15, 10, 13, 14, 1, 7, 4, 12, 9, 6, 0], + [12, 8, 2, 1, 13, 4, 15, 6, 7, 0, 10, 5, 3, 14, 9, 11], + [7, 15, 5, 10, 8, 1, 6, 13, 0, 9, 3, 14, 11, 4, 2, 12], + [5, 13, 15, 6, 9, 2, 12, 10, 11, 7, 8, 1, 4, 3, 14, 0], + [8, 14, 2, 5, 6, 9, 1, 12, 15, 4, 11, 0, 13, 10, 3, 7], + [1, 7, 14, 13, 0, 5, 8, 3, 4, 15, 10, 6, 9, 12, 11, 2], + ]; + const H0: Block = [0; 32]; + const NAME: &'static str = "Gost94s2015"; +} + +/// Test parameters. +#[derive(Copy, Clone, Default)] +pub struct TestParam; + +impl Gost94Params for TestParam { + const S_BOX: SBox = [ + [4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3], + [14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9], + [5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11], + [7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3], + [6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2], + [4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14], + [13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12], + [1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12], + ]; + const H0: Block = [0; 32]; + const NAME: &'static str = "Gost94Test"; +} diff --git a/gost94/src/s2015.rs b/gost94/src/s2015.rs deleted file mode 100644 index ac01a5c29..000000000 --- a/gost94/src/s2015.rs +++ /dev/null @@ -1,12 +0,0 @@ -const S2015: SBox = [ - [12, 4, 6, 2, 10, 5, 11, 9, 14, 8, 13, 7, 0, 3, 15, 1], - [6, 8, 2, 3, 9, 10, 5, 12, 1, 14, 4, 7, 11, 13, 0, 15], - [11, 3, 5, 8, 2, 15, 10, 13, 14, 1, 7, 4, 12, 9, 6, 0], - [12, 8, 2, 1, 13, 4, 15, 6, 7, 0, 10, 5, 3, 14, 9, 11], - [7, 15, 5, 10, 8, 1, 6, 13, 0, 9, 3, 14, 11, 4, 2, 12], - [5, 13, 15, 6, 9, 2, 12, 10, 11, 7, 8, 1, 4, 3, 14, 0], - [8, 14, 2, 5, 6, 9, 1, 12, 15, 4, 11, 0, 13, 10, 3, 7], - [1, 7, 14, 13, 0, 5, 8, 3, 4, 15, 10, 6, 9, 12, 11, 2], -]; - -gost94_impl!(Gost94s2015, S2015); diff --git a/gost94/src/test_param.rs b/gost94/src/test_param.rs deleted file mode 100644 index f1b202f6e..000000000 --- a/gost94/src/test_param.rs +++ /dev/null @@ -1,12 +0,0 @@ -const S_TEST: SBox = [ - [4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3], - [14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9], - [5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11], - [7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3], - [6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2], - [4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14], - [13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12], - [1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12], -]; - -gost94_impl!(Gost94Test, S_TEST); diff --git a/gost94/tests/data/cryptopro.blb b/gost94/tests/data/cryptopro.blb index 8ff577b11..ace31477a 100644 Binary files a/gost94/tests/data/cryptopro.blb and b/gost94/tests/data/cryptopro.blb differ diff --git a/gost94/tests/data/test.blb b/gost94/tests/data/test.blb index 12fcc2b56..94f08fe9a 100644 Binary files a/gost94/tests/data/test.blb and b/gost94/tests/data/test.blb differ diff --git a/groestl/CHANGELOG.md b/groestl/CHANGELOG.md index 08c48c032..9c2c575bf 100644 --- a/groestl/CHANGELOG.md +++ b/groestl/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## 0.10.0 (2021-11-22) +### Changed +- Update to `digest` v0.10 and significantly improve performance ([#217]) + +[#217]: https://github.com/RustCrypto/hashes/pull/217 + ## 0.9.0 (2020-06-12) ### Changed - Bump `opaque-debug` to v0.3.0 ([#168]) diff --git a/groestl/Cargo.toml b/groestl/Cargo.toml index 1408b7f66..307111bdd 100644 --- a/groestl/Cargo.toml +++ b/groestl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "groestl" -version = "0.9.0" +version = "0.10.0" # Also update html_root_url in lib.rs when bumping this description = "Grøstl hash function" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -12,12 +12,10 @@ keywords = ["crypto", "groestl", "grostl", "hash", "digest"] categories = ["cryptography", "no-std"] [dependencies] -digest = "0.9" -block-buffer = "0.9" -opaque-debug = "0.3" +digest = "0.10" [dev-dependencies] -digest = { version = "0.9", features = ["dev"] } +digest = { version = "0.10", features = ["dev"] } hex-literal = "0.2" [features] diff --git a/groestl/LICENSE-MIT b/groestl/LICENSE-MIT index 3d35f5c64..f39f9ff82 100644 --- a/groestl/LICENSE-MIT +++ b/groestl/LICENSE-MIT @@ -1,4 +1,4 @@ -Copyright (c) 2017 Gulshan Singh +Copyright (c) 2020 RustCrypto Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/groestl/src/compress1024.rs b/groestl/src/compress1024.rs new file mode 100644 index 000000000..ebfd080fc --- /dev/null +++ b/groestl/src/compress1024.rs @@ -0,0 +1,99 @@ +#![allow(clippy::needless_range_loop)] +use crate::table::TABLE; +use core::{convert::TryInto, u64}; + +pub(crate) const COLS: usize = 16; +const ROUNDS: u64 = 14; +type Block = super::Block; + +#[inline(always)] +fn column(x: &[u64; COLS], c: [usize; 8]) -> u64 { + let mut t = 0; + for i in 0..8 { + let sl = 8 * (7 - i); + let idx = ((x[c[i]] >> sl) & 0xFF) as usize; + t ^= TABLE[i][idx]; + } + t +} + +#[inline(always)] +fn rndq(mut x: [u64; COLS], r: u64) -> [u64; COLS] { + for i in 0..COLS { + x[i] ^= u64::MAX.wrapping_sub((i as u64) << 4) ^ r; + } + [ + column(&x, [1, 3, 5, 11, 0, 2, 4, 6]), + column(&x, [2, 4, 6, 12, 1, 3, 5, 7]), + column(&x, [3, 5, 7, 13, 2, 4, 6, 8]), + column(&x, [4, 6, 8, 14, 3, 5, 7, 9]), + column(&x, [5, 7, 9, 15, 4, 6, 8, 10]), + column(&x, [6, 8, 10, 0, 5, 7, 9, 11]), + column(&x, [7, 9, 11, 1, 6, 8, 10, 12]), + column(&x, [8, 10, 12, 2, 7, 9, 11, 13]), + column(&x, [9, 11, 13, 3, 8, 10, 12, 14]), + column(&x, [10, 12, 14, 4, 9, 11, 13, 15]), + column(&x, [11, 13, 15, 5, 10, 12, 14, 0]), + column(&x, [12, 14, 0, 6, 11, 13, 15, 1]), + column(&x, [13, 15, 1, 7, 12, 14, 0, 2]), + column(&x, [14, 0, 2, 8, 13, 15, 1, 3]), + column(&x, [15, 1, 3, 9, 14, 0, 2, 4]), + column(&x, [0, 2, 4, 10, 15, 1, 3, 5]), + ] +} + +#[inline(always)] +fn rndp(mut x: [u64; COLS], r: u64) -> [u64; COLS] { + for i in 0..COLS { + x[i] ^= ((i as u64) << 60) ^ r; + } + [ + column(&x, [0, 1, 2, 3, 4, 5, 6, 11]), + column(&x, [1, 2, 3, 4, 5, 6, 7, 12]), + column(&x, [2, 3, 4, 5, 6, 7, 8, 13]), + column(&x, [3, 4, 5, 6, 7, 8, 9, 14]), + column(&x, [4, 5, 6, 7, 8, 9, 10, 15]), + column(&x, [5, 6, 7, 8, 9, 10, 11, 0]), + column(&x, [6, 7, 8, 9, 10, 11, 12, 1]), + column(&x, [7, 8, 9, 10, 11, 12, 13, 2]), + column(&x, [8, 9, 10, 11, 12, 13, 14, 3]), + column(&x, [9, 10, 11, 12, 13, 14, 15, 4]), + column(&x, [10, 11, 12, 13, 14, 15, 0, 5]), + column(&x, [11, 12, 13, 14, 15, 0, 1, 6]), + column(&x, [12, 13, 14, 15, 0, 1, 2, 7]), + column(&x, [13, 14, 15, 0, 1, 2, 3, 8]), + column(&x, [14, 15, 0, 1, 2, 3, 4, 9]), + column(&x, [15, 0, 1, 2, 3, 4, 5, 10]), + ] +} + +pub(crate) fn compress(h: &mut [u64; COLS], block: &Block) { + let mut q = [0u64; COLS]; + for (chunk, v) in block.chunks_exact(8).zip(q.iter_mut()) { + *v = u64::from_be_bytes(chunk.try_into().unwrap()); + } + let mut p = [0u64; COLS]; + for i in 0..COLS { + p[i] = h[i] ^ q[i]; + } + for i in 0..ROUNDS { + q = rndq(q, i); + } + for i in 0..ROUNDS { + p = rndp(p, i << 56); + } + for i in 0..COLS { + h[i] ^= q[i] ^ p[i]; + } +} + +pub(crate) fn p(h: &[u64; COLS]) -> [u64; COLS] { + let mut p = *h; + for i in 0..ROUNDS { + p = rndp(p, i << 56); + } + for i in 0..COLS { + p[i] ^= h[i]; + } + p +} diff --git a/groestl/src/compress512.rs b/groestl/src/compress512.rs new file mode 100644 index 000000000..1db8d4091 --- /dev/null +++ b/groestl/src/compress512.rs @@ -0,0 +1,83 @@ +#![allow(clippy::needless_range_loop)] +use crate::table::TABLE; +use core::{convert::TryInto, u64}; +type Block = super::Block; + +pub(crate) const COLS: usize = 8; +const ROUNDS: u64 = 10; + +#[inline(always)] +fn column(x: &[u64; COLS], c: [usize; 8]) -> u64 { + let mut t = 0; + for i in 0..8 { + let sl = 8 * (7 - i); + let idx = ((x[c[i]] >> sl) & 0xFF) as usize; + t ^= TABLE[i][idx]; + } + t +} + +#[inline(always)] +fn rndq(mut x: [u64; COLS], r: u64) -> [u64; COLS] { + for i in 0..COLS { + x[i] ^= u64::MAX.wrapping_sub((i as u64) << 4) ^ r; + } + [ + column(&x, [1, 3, 5, 7, 0, 2, 4, 6]), + column(&x, [2, 4, 6, 0, 1, 3, 5, 7]), + column(&x, [3, 5, 7, 1, 2, 4, 6, 0]), + column(&x, [4, 6, 0, 2, 3, 5, 7, 1]), + column(&x, [5, 7, 1, 3, 4, 6, 0, 2]), + column(&x, [6, 0, 2, 4, 5, 7, 1, 3]), + column(&x, [7, 1, 3, 5, 6, 0, 2, 4]), + column(&x, [0, 2, 4, 6, 7, 1, 3, 5]), + ] +} + +#[inline(always)] +fn rndp(mut x: [u64; COLS], r: u64) -> [u64; COLS] { + for i in 0..COLS { + x[i] ^= ((i as u64) << 60) ^ r; + } + [ + column(&x, [0, 1, 2, 3, 4, 5, 6, 7]), + column(&x, [1, 2, 3, 4, 5, 6, 7, 0]), + column(&x, [2, 3, 4, 5, 6, 7, 0, 1]), + column(&x, [3, 4, 5, 6, 7, 0, 1, 2]), + column(&x, [4, 5, 6, 7, 0, 1, 2, 3]), + column(&x, [5, 6, 7, 0, 1, 2, 3, 4]), + column(&x, [6, 7, 0, 1, 2, 3, 4, 5]), + column(&x, [7, 0, 1, 2, 3, 4, 5, 6]), + ] +} + +pub(crate) fn compress(h: &mut [u64; COLS], block: &Block) { + let mut q = [0u64; COLS]; + for (chunk, v) in block.chunks_exact(8).zip(q.iter_mut()) { + *v = u64::from_be_bytes(chunk.try_into().unwrap()); + } + let mut p = [0u64; COLS]; + for i in 0..COLS { + p[i] = h[i] ^ q[i]; + } + for i in 0..ROUNDS { + q = rndq(q, i); + } + for i in 0..ROUNDS { + p = rndp(p, i << 56); + } + for i in 0..COLS { + h[i] ^= q[i] ^ p[i]; + } +} + +pub(crate) fn p(h: &[u64; COLS]) -> [u64; COLS] { + let mut p = *h; + for i in 0..ROUNDS { + p = rndp(p, i << 56); + } + for i in 0..COLS { + p[i] ^= h[i]; + } + p +} diff --git a/groestl/src/consts.rs b/groestl/src/consts.rs deleted file mode 100644 index 6b09c6a25..000000000 --- a/groestl/src/consts.rs +++ /dev/null @@ -1,55 +0,0 @@ -pub const SBOX: [u8; 256] = [ - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, -]; - -pub const C_P: [u8; 128] = [ - 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -]; -pub const C_Q: [u8; 128] = [ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xef, 0xdf, 0xcf, 0xbf, 0xaf, 0x9f, 0x8f, 0x7f, 0x6f, 0x5f, 0x4f, 0x3f, 0x2f, 0x1f, 0x0f, -]; - -pub const B: [[u8; 8]; 8] = [ - [2, 2, 3, 4, 5, 3, 5, 7], - [7, 2, 2, 3, 4, 5, 3, 5], - [5, 7, 2, 2, 3, 4, 5, 3], - [3, 5, 7, 2, 2, 3, 4, 5], - [5, 3, 5, 7, 2, 2, 3, 4], - [4, 5, 3, 5, 7, 2, 2, 3], - [3, 4, 5, 3, 5, 7, 2, 2], - [2, 3, 4, 5, 3, 5, 7, 2], -]; - -pub const SHIFTS_P: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; -pub const SHIFTS_Q: [u8; 8] = [1, 3, 5, 7, 0, 2, 4, 6]; -pub const SHIFTS_P_WIDE: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 11]; -pub const SHIFTS_Q_WIDE: [u8; 8] = [1, 3, 5, 11, 0, 2, 4, 6]; diff --git a/groestl/src/groestl.rs b/groestl/src/groestl.rs deleted file mode 100644 index 1690de283..000000000 --- a/groestl/src/groestl.rs +++ /dev/null @@ -1,76 +0,0 @@ -use block_buffer::BlockBuffer; -use core::ops::Div; -use digest::generic_array::typenum::{Quot, U8}; -use digest::generic_array::{ArrayLength, GenericArray}; - -use crate::state::{xor_generic_array, GroestlState}; - -#[derive(Clone)] -pub struct Groestl -where - BlockSize: ArrayLength + Div + Default, - BlockSize::ArrayType: Copy, - Quot: ArrayLength, -{ - buffer: BlockBuffer, - state: GroestlState, - pub output_size: usize, -} - -impl Groestl -where - BlockSize: ArrayLength + Div + Default, - BlockSize::ArrayType: Copy, - Quot: ArrayLength, - Self: Clone, -{ - pub fn new(output_size: usize) -> Result { - match BlockSize::to_usize() { - 128 => { - if output_size <= 32 || output_size > 64 { - return Err(digest::InvalidOutputSize); - } - } - 64 => { - if output_size == 0 || output_size > 32 { - return Err(digest::InvalidOutputSize); - } - } - _ => unreachable!(), - }; - - let state = GroestlState::new(output_size); - Ok(Groestl { - buffer: Default::default(), - state, - output_size, - }) - } - - pub fn process(&mut self, input: &[u8]) { - let s = &mut self.state; - self.buffer.input_block(input, |b| s.compress(b)); - } - - pub fn finalize(&mut self) -> GenericArray { - let res = { - let state = &mut self.state; - let l = if self.buffer.remaining() <= 8 { - state.num_blocks + 2 - } else { - state.num_blocks + 1 - }; - self.buffer.len64_padding_be(l, |b| state.compress(b)); - xor_generic_array(&state.p(&state.state), &state.state) - }; - - self.buffer = Default::default(); - self.state = GroestlState::new(self.output_size); - res - } - - pub fn reset(&mut self) { - self.state = GroestlState::new(self.output_size); - self.buffer.reset(); - } -} diff --git a/groestl/src/lib.rs b/groestl/src/lib.rs old mode 100755 new mode 100644 index d4c8155ec..d7fb0d617 --- a/groestl/src/lib.rs +++ b/groestl/src/lib.rs @@ -2,14 +2,7 @@ //! //! # Usage //! -//! Groestl can produce a digest of any size between 1 and 64 bytes inclusive. -//! This crate defines the common digest sizes (`Groestl224`, `Groestl256`, -//! `Groestl384`, and `Groestl512`), but allows you to specify a custom size -//! with the `GroestlSmall` and `GroestlBig` structs. `GroestlSmall` allows you -//! to specify a digest size between 1 and 32 inclusive, and `GroestlBig` allows -//! you to specify a digest size between 33 and 64 inclusive. -//! -//! ```rust +//! ``` //! use groestl::{Digest, Groestl256}; //! use hex_literal::hex; //! @@ -34,33 +27,204 @@ #![no_std] #![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_root_url = "https://docs.rs/groestl/0.10.0" )] #![deny(unsafe_code)] #![warn(rust_2018_idioms)] -#[cfg(feature = "std")] -extern crate std; - pub use digest::{self, Digest}; -mod consts; -mod groestl; -mod matrix; -mod state; -#[macro_use] -mod macros; - -use crate::groestl::Groestl; -use digest::consts::{U128, U28, U32, U48, U64}; -use digest::generic_array::typenum::Unsigned; -use digest::{BlockInput, FixedOutputDirty, InvalidOutputSize, Reset, Update, VariableOutputDirty}; - -impl_groestl!(Groestl512, U64, U128); -impl_groestl!(Groestl384, U48, U128); -impl_groestl!(Groestl256, U32, U64); -impl_groestl!(Groestl224, U28, U64); - -impl_variable_groestl!(GroestlBig, U128, 32, 64); -impl_variable_groestl!(GroestlSmall, U64, 0, 32); +use core::fmt; +use digest::{ + block_buffer::Eager, + core_api::{ + AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, + CtVariableCoreWrapper, RtVariableCoreWrapper, UpdateCore, VariableOutputCore, + }, + generic_array::typenum::{Unsigned, U128, U28, U32, U48, U64}, + HashMarker, InvalidOutputSize, +}; + +mod compress1024; +mod compress512; +mod table; + +/// Lowest-level core hasher state of the short Groestl variant. +#[derive(Clone)] +pub struct GroestlShortVarCore { + state: [u64; compress512::COLS], + blocks_len: u64, +} + +impl HashMarker for GroestlShortVarCore {} + +impl BlockSizeUser for GroestlShortVarCore { + type BlockSize = U64; +} + +impl BufferKindUser for GroestlShortVarCore { + type BufferKind = Eager; +} + +impl UpdateCore for GroestlShortVarCore { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + self.blocks_len += blocks.len() as u64; + for block in blocks { + compress512::compress(&mut self.state, block); + } + } +} + +impl VariableOutputCore for GroestlShortVarCore { + type MaxOutputSize = U32; + + #[inline] + fn new(output_size: usize) -> Result { + if output_size > Self::MaxOutputSize::USIZE { + return Err(InvalidOutputSize); + } + let mut state = [0; compress512::COLS]; + state[compress512::COLS - 1] = 8 * output_size as u64; + let blocks_len = 0; + Ok(Self { state, blocks_len }) + } + + #[inline] + fn finalize_variable_core( + &mut self, + buffer: &mut Buffer, + output_size: usize, + f: impl FnOnce(&[u8]), + ) { + let blocks_len = if buffer.remaining() <= 8 { + self.blocks_len + 2 + } else { + self.blocks_len + 1 + }; + buffer.len64_padding_be(blocks_len, |b| compress512::compress(&mut self.state, b)); + let res = compress512::p(&self.state); + let mut buf = [0; Self::MaxOutputSize::USIZE]; + let n = compress512::COLS / 2; + for (chunk, v) in buf.chunks_exact_mut(8).zip(res[n..].iter()) { + chunk.copy_from_slice(&v.to_be_bytes()); + } + f(&buf[buf.len() - output_size..]) + } +} + +impl AlgorithmName for GroestlShortVarCore { + #[inline] + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("GroestlShort") + } +} + +impl fmt::Debug for GroestlShortVarCore { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("GroestlShortVarCore { ... }") + } +} + +/// Short Groestl variant which allows to choose output size at runtime. +pub type GroestlShortVar = RtVariableCoreWrapper; +/// Core hasher state of the short Groestl variant generic over output size. +pub type GroestlShortCore = CtVariableCoreWrapper; +/// Hasher state of the short Groestl variant generic over output size. +pub type GroestlShort = CoreWrapper>; + +/// Groestl-224 hasher state. +pub type Groestl224 = CoreWrapper>; +/// Groestl-256 hasher state. +pub type Groestl256 = CoreWrapper>; + +/// Lowest-level core hasher state of the long Groestl variant. +#[derive(Clone)] +pub struct GroestlLongVarCore { + state: [u64; compress1024::COLS], + blocks_len: u64, +} + +impl HashMarker for GroestlLongVarCore {} + +impl BlockSizeUser for GroestlLongVarCore { + type BlockSize = U128; +} + +impl BufferKindUser for GroestlLongVarCore { + type BufferKind = Eager; +} + +impl UpdateCore for GroestlLongVarCore { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + self.blocks_len += blocks.len() as u64; + for block in blocks { + compress1024::compress(&mut self.state, block); + } + } +} + +impl VariableOutputCore for GroestlLongVarCore { + type MaxOutputSize = U64; + + #[inline] + fn new(output_size: usize) -> Result { + if output_size > Self::MaxOutputSize::USIZE { + return Err(InvalidOutputSize); + } + let mut state = [0; compress1024::COLS]; + state[compress1024::COLS - 1] = 8 * output_size as u64; + let blocks_len = 0; + Ok(Self { state, blocks_len }) + } + + #[inline] + fn finalize_variable_core( + &mut self, + buffer: &mut Buffer, + output_size: usize, + f: impl FnOnce(&[u8]), + ) { + let blocks_len = if buffer.remaining() <= 8 { + self.blocks_len + 2 + } else { + self.blocks_len + 1 + }; + buffer.len64_padding_be(blocks_len, |b| compress1024::compress(&mut self.state, b)); + let res = compress1024::p(&self.state); + let mut buf = [0; Self::MaxOutputSize::USIZE]; + let n = compress1024::COLS / 2; + for (chunk, v) in buf.chunks_exact_mut(8).zip(res[n..].iter()) { + chunk.copy_from_slice(&v.to_be_bytes()); + } + f(&buf[buf.len() - output_size..]) + } +} + +impl AlgorithmName for GroestlLongVarCore { + #[inline] + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("GroestlLong") + } +} + +impl fmt::Debug for GroestlLongVarCore { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("GroestlLongVarCore { ... }") + } +} + +/// Long Groestl variant which allows to choose output size at runtime. +pub type GroestlLongVar = RtVariableCoreWrapper; +/// Core hasher state of the long Groestl variant generic over output size. +pub type GroestlLongCore = CtVariableCoreWrapper; +/// Hasher state of the long Groestl variant generic over output size. +pub type GroestlLong = CoreWrapper>; + +/// Groestl-384 hasher state. +pub type Groestl384 = CoreWrapper>; +/// Groestl-512 hasher state. +pub type Groestl512 = CoreWrapper>; diff --git a/groestl/src/macros.rs b/groestl/src/macros.rs deleted file mode 100644 index 00a54e338..000000000 --- a/groestl/src/macros.rs +++ /dev/null @@ -1,95 +0,0 @@ -macro_rules! impl_groestl { - ($state:ident, $output:ident, $block:ident) => { - #[derive(Clone)] - pub struct $state { - groestl: Groestl<$block>, - } - - impl Default for $state { - fn default() -> Self { - $state { - groestl: Groestl::new($output::to_usize()).unwrap(), - } - } - } - - impl BlockInput for $state { - type BlockSize = $block; - } - - impl Update for $state { - fn update(&mut self, input: impl AsRef<[u8]>) { - let input = input.as_ref(); - self.groestl.process(input); - } - } - - impl FixedOutputDirty for $state { - type OutputSize = $output; - - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - let block = self.groestl.finalize(); - let n = block.len() - Self::OutputSize::to_usize(); - out.copy_from_slice(&block[n..]) - } - } - - impl Reset for $state { - fn reset(&mut self) { - self.groestl.reset() - } - } - - opaque_debug::implement!($state); - digest::impl_write!($state); - }; -} - -macro_rules! impl_variable_groestl { - ($state:ident, $block:ident, $min:expr, $max:expr) => { - #[derive(Clone)] - pub struct $state { - groestl: Groestl<$block>, - } - - impl BlockInput for $state { - type BlockSize = $block; - } - - impl Update for $state { - fn update(&mut self, input: impl AsRef<[u8]>) { - self.groestl.process(input.as_ref()); - } - } - - impl VariableOutputDirty for $state { - fn new(output_size: usize) -> Result { - if output_size == $min || output_size > $max { - return Err(InvalidOutputSize); - } - Ok($state { - groestl: Groestl::new(output_size).unwrap(), - }) - } - - fn output_size(&self) -> usize { - self.groestl.output_size - } - - fn finalize_variable_dirty(&mut self, f: impl FnOnce(&[u8])) { - let block = self.groestl.finalize(); - let n = block.len() - self.groestl.output_size; - f(&block[n..]); - } - } - - impl Reset for $state { - fn reset(&mut self) { - self.groestl.reset() - } - } - - opaque_debug::implement!($state); - digest::impl_write!($state); - }; -} diff --git a/groestl/src/matrix.rs b/groestl/src/matrix.rs deleted file mode 100644 index 433ddb66f..000000000 --- a/groestl/src/matrix.rs +++ /dev/null @@ -1,87 +0,0 @@ -use core::ops::{Index, IndexMut}; -use digest::generic_array::{ArrayLength, GenericArray}; - -#[derive(Debug, Eq, PartialEq)] -pub struct Matrix>, C: ArrayLength> { - pub state: GenericArray, R>, -} - -impl Default for Matrix -where - R: ArrayLength>, - C: ArrayLength, -{ - fn default() -> Self { - Matrix { - state: GenericArray::default(), - } - } -} - -impl Index for Matrix -where - R: ArrayLength>, - C: ArrayLength, -{ - type Output = GenericArray; - - fn index(&self, index: usize) -> &Self::Output { - &self.state[index] - } -} - -impl IndexMut for Matrix -where - R: ArrayLength>, - C: ArrayLength, -{ - fn index_mut(&mut self, index: usize) -> &mut Self::Output { - &mut self.state[index] - } -} - -fn poly_mul(a: u8, b: usize) -> usize { - let mut val = match a { - 2 => b << 1, - 3 => b ^ poly_mul(2, b), - 4 => b << 2, - 5 => b ^ poly_mul(4, b), - 7 => b ^ poly_mul(2, b) ^ poly_mul(4, b), - _ => unreachable!(), - }; - - if val >= 512 { - val ^= 0x11b << 1; - } - if val >= 256 { - val ^= 0x11b; - } - val -} - -impl Matrix -where - R: ArrayLength>, - C: ArrayLength, -{ - pub fn rows(&self) -> usize { - R::to_usize() - } - - pub fn cols(&self) -> usize { - C::to_usize() - } - - pub fn mul_array(&self, a: &[[u8; 8]; 8]) -> Self { - let mut res = Matrix::default(); - for i in 0..8 { - for j in 0..self.cols() { - for k in 0..8 { - res[i][j] ^= poly_mul(a[i][k], self[k][j] as usize) as u8; - } - } - } - - res - } -} diff --git a/groestl/src/state.rs b/groestl/src/state.rs deleted file mode 100644 index f1e4dd424..000000000 --- a/groestl/src/state.rs +++ /dev/null @@ -1,293 +0,0 @@ -use core::ops::Div; - -use crate::consts::{B, C_P, C_Q, SBOX, SHIFTS_P, SHIFTS_P_WIDE, SHIFTS_Q, SHIFTS_Q_WIDE}; -use crate::matrix::Matrix; -use digest::generic_array::typenum::{Quot, U8}; -use digest::generic_array::{ArrayLength, GenericArray}; - -#[derive(Copy, Clone)] -pub struct GroestlState -where - BlockSize: ArrayLength + Div, - BlockSize::ArrayType: Copy, - Quot: ArrayLength, -{ - pub state: GenericArray, - rounds: u8, - pub num_blocks: u64, -} - -pub fn xor_generic_array>( - a1: &GenericArray, - a2: &GenericArray, -) -> GenericArray { - let mut res = GenericArray::default(); - for i in 0..L::to_usize() { - res[i] = a1[i] ^ a2[i]; - } - res -} - -fn gcd(a: usize, b: usize) -> usize { - if b == 0 { - return a; - } - gcd(b, a % b) -} - -impl GroestlState -where - BlockSize: ArrayLength + Div, - BlockSize::ArrayType: Copy, - Quot: ArrayLength, -{ - pub fn new(output_size: usize) -> Self { - let block_bytes = BlockSize::to_usize(); - let output_bits = output_size * 8; - - let mut state = GenericArray::default(); - let n = output_bits as u64; - state[block_bytes - 8..].copy_from_slice(&n.to_be_bytes()); - let rounds = match block_bytes { - 128 => 14, - 64 => 10, - _ => unreachable!(), - }; - - GroestlState { - state, - rounds, - num_blocks: 0, - } - } - - fn wide(&self) -> bool { - match BlockSize::to_usize() { - 128 => true, - 64 => false, - _ => unreachable!(), - } - } - - pub fn compress(&mut self, input_block: &GenericArray) { - self.state = xor_generic_array( - &xor_generic_array( - &self.p(&xor_generic_array(&self.state, input_block)), - &self.q(input_block), - ), - &self.state, - ); - self.num_blocks += 1; - } - - fn block_to_matrix( - &self, - block: &GenericArray, - ) -> Matrix> { - let mut matrix = Matrix::>::default(); - - let rows = matrix.rows(); - for i in 0..matrix.cols() { - for j in 0..rows { - matrix[j][i] = block[i * rows + j]; - } - } - - matrix - } - - fn matrix_to_block( - &self, - matrix: &Matrix>, - ) -> GenericArray { - let mut block = GenericArray::default(); - - let rows = matrix.rows(); - for i in 0..matrix.cols() { - for j in 0..rows { - block[i * rows + j] = matrix[j][i]; - } - } - - block - } - - pub fn p(&self, block: &GenericArray) -> GenericArray { - let shifts = if self.wide() { SHIFTS_P_WIDE } else { SHIFTS_P }; - let mut matrix = self.block_to_matrix(block); - for round in 0..self.rounds { - self.add_round_constant(&mut matrix, C_P, round); - self.sub_bytes(&mut matrix); - self.shift_bytes(&mut matrix, shifts); - matrix = matrix.mul_array(&B); - } - self.matrix_to_block(&matrix) - } - - fn q(&self, block: &GenericArray) -> GenericArray { - let shifts = if self.wide() { SHIFTS_Q_WIDE } else { SHIFTS_Q }; - let mut matrix = self.block_to_matrix(block); - for round in 0..self.rounds { - self.add_round_constant(&mut matrix, C_Q, round); - self.sub_bytes(&mut matrix); - self.shift_bytes(&mut matrix, shifts); - matrix = matrix.mul_array(&B); - } - self.matrix_to_block(&matrix) - } - - fn add_round_constant( - &self, - matrix: &mut Matrix>, - c: [u8; 128], - round: u8, - ) { - for i in 0..matrix.rows() { - for j in 0..matrix.cols() { - matrix[i][j] ^= c[i * 16 + j]; - - if (c[0] == 0x00 && i == 0) || (c[0] == 0xff && i == 7) { - matrix[i][j] ^= round; - } - } - } - } - - fn sub_bytes(&self, matrix: &mut Matrix>) { - for i in 0..matrix.rows() { - for j in 0..matrix.cols() { - matrix[i][j] = SBOX[matrix[i][j] as usize]; - } - } - } - - fn shift_bytes(&self, matrix: &mut Matrix>, shifts: [u8; 8]) { - let cols = matrix.cols(); - for i in 0..matrix.rows() { - let shift = shifts[i] as usize; - if shift == 0 { - continue; - } - let d = gcd(shift, cols); - for j in 0..d { - let mut k = j; - let tmp = matrix[i][k]; - loop { - let pos = k.wrapping_add(shift) % cols; - if pos == j { - break; - } - matrix[i][k] = matrix[i][pos]; - k = pos; - } - matrix[i][k] = tmp; - } - } - } -} - -#[cfg(test)] -mod test { - use super::{xor_generic_array, GroestlState}; - use crate::consts::{C_P, C_Q, SHIFTS_P}; - use digest::generic_array::typenum::U64; - use digest::generic_array::GenericArray; - - fn get_padding_block() -> GenericArray { - let padding_block: [u8; 64] = [ - 128, 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, 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, 1, - ]; - - GenericArray::clone_from_slice(&padding_block) - } - - #[test] - fn test_shift_bytes() { - let s = GroestlState::::new(32); - let mut block = GenericArray::default(); - for i in 0..64 { - block[i] = i as u8; - } - let mut matrix = s.block_to_matrix(&block); - s.shift_bytes(&mut matrix, SHIFTS_P); - let block = s.matrix_to_block(&matrix); - let expected = [ - 0, 9, 18, 27, 36, 45, 54, 63, 8, 17, 26, 35, 44, 53, 62, 7, 16, 25, 34, 43, 52, 61, 6, - 15, 24, 33, 42, 51, 60, 5, 14, 23, 32, 41, 50, 59, 4, 13, 22, 31, 40, 49, 58, 3, 12, - 21, 30, 39, 48, 57, 2, 11, 20, 29, 38, 47, 56, 1, 10, 19, 28, 37, 46, 55, - ]; - assert_eq!(&block[..], &expected[..]); - } - - #[test] - fn test_p() { - let padding_chunk = get_padding_block(); - let s = GroestlState::::new(32); - let block = xor_generic_array(&s.state, GenericArray::from_slice(&padding_chunk)); - - let p_block = s.p(&block); - let expected = [ - 247, 236, 141, 217, 73, 225, 112, 216, 1, 155, 85, 192, 152, 168, 174, 72, 112, 253, - 159, 53, 7, 6, 8, 115, 58, 242, 7, 115, 148, 150, 157, 25, 18, 220, 11, 5, 178, 10, - 110, 94, 44, 56, 110, 67, 107, 234, 102, 163, 243, 212, 49, 25, 46, 17, 170, 84, 5, 76, - 239, 51, 4, 107, 94, 20, - ]; - assert_eq!(&p_block[..], &expected[..]); - } - - #[test] - fn test_q() { - let padding_chunk = get_padding_block(); - let s = GroestlState::::new(32); - let q_block = s.q(GenericArray::from_slice(&padding_chunk)); - let expected = [ - 189, 183, 105, 133, 208, 106, 34, 36, 82, 37, 180, 250, 229, 59, 230, 223, 215, 245, - 53, 117, 167, 139, 150, 186, 210, 17, 220, 57, 116, 134, 209, 51, 124, 108, 84, 91, 79, - 103, 148, 27, 135, 183, 144, 226, 59, 242, 87, 81, 109, 211, 84, 185, 192, 172, 88, - 210, 8, 121, 31, 242, 158, 227, 207, 13, - ]; - assert_eq!(&q_block[..], &expected[..]); - } - - #[test] - fn test_block_to_matrix() { - let s = GroestlState::::new(32); - let mut block1 = GenericArray::default(); - for i in 0..block1.len() { - block1[i] = i as u8; - } - let m = s.block_to_matrix(&block1); - let block2 = s.matrix_to_block(&m); - assert_eq!(block1, block2); - } - - #[test] - fn test_add_round_constant() { - let padding_chunk = get_padding_block(); - let s = GroestlState::::new(32); - - let mut m = s.block_to_matrix(GenericArray::from_slice(&padding_chunk)); - s.add_round_constant(&mut m, C_P, 0); - let b = s.matrix_to_block(&m); - let expected = [ - 128, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, - 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, - 0, 112, 0, 0, 0, 0, 0, 0, 1, - ]; - assert_eq!(&b[..], &expected[..]); - - let mut m = s.block_to_matrix(GenericArray::from_slice(&padding_chunk)); - s.add_round_constant(&mut m, C_Q, 0); - let b = s.matrix_to_block(&m); - let expected = [ - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8e, - ]; - assert_eq!(&b[..], &expected[..]); - } -} diff --git a/groestl/src/table.rs b/groestl/src/table.rs new file mode 100644 index 000000000..fe1e729dc --- /dev/null +++ b/groestl/src/table.rs @@ -0,0 +1,11 @@ +#[rustfmt::skip] +pub(crate) const TABLE: [[u64; 256]; 8] = [ + [0xc632f4a5f497a5c6, 0xf86f978497eb84f8, 0xee5eb099b0c799ee, 0xf67a8c8d8cf78df6, 0xffe8170d17e50dff, 0xd60adcbddcb7bdd6, 0xde16c8b1c8a7b1de, 0x916dfc54fc395491, 0x6090f050f0c05060, 0x0207050305040302, 0xce2ee0a9e087a9ce, 0x56d1877d87ac7d56, 0xe7cc2b192bd519e7, 0xb513a662a67162b5, 0x4d7c31e6319ae64d, 0xec59b59ab5c39aec, 0x8f40cf45cf05458f, 0x1fa3bc9dbc3e9d1f, 0x8949c040c0094089, 0xfa68928792ef87fa, 0xefd03f153fc515ef, 0xb29426eb267febb2, 0x8ece40c94007c98e, 0xfbe61d0b1ded0bfb, 0x416e2fec2f82ec41, 0xb31aa967a97d67b3, 0x5f431cfd1cbefd5f, 0x456025ea258aea45, 0x23f9dabfda46bf23, 0x535102f702a6f753, 0xe445a196a1d396e4, 0x9b76ed5bed2d5b9b, 0x75285dc25deac275, 0xe1c5241c24d91ce1, 0x3dd4e9aee97aae3d, 0x4cf2be6abe986a4c, 0x6c82ee5aeed85a6c, 0x7ebdc341c3fc417e, 0xf5f3060206f102f5, 0x8352d14fd11d4f83, 0x688ce45ce4d05c68, 0x515607f407a2f451, 0xd18d5c345cb934d1, 0xf9e1180818e908f9, 0xe24cae93aedf93e2, 0xab3e9573954d73ab, 0x6297f553f5c45362, 0x2a6b413f41543f2a, 0x081c140c14100c08, 0x9563f652f6315295, 0x46e9af65af8c6546, 0x9d7fe25ee2215e9d, 0x3048782878602830, 0x37cff8a1f86ea137, 0x0a1b110f11140f0a, 0x2febc4b5c45eb52f, 0x0e151b091b1c090e, 0x247e5a365a483624, 0x1badb69bb6369b1b, 0xdf98473d47a53ddf, 0xcda76a266a8126cd, 0x4ef5bb69bb9c694e, 0x7f334ccd4cfecd7f, 0xea50ba9fbacf9fea, 0x123f2d1b2d241b12, 0x1da4b99eb93a9e1d, 0x58c49c749cb07458, 0x3446722e72682e34, 0x3641772d776c2d36, 0xdc11cdb2cda3b2dc, 0xb49d29ee2973eeb4, 0x5b4d16fb16b6fb5b, 0xa4a501f60153f6a4, 0x76a1d74dd7ec4d76, 0xb714a361a37561b7, 0x7d3449ce49face7d, 0x52df8d7b8da47b52, 0xdd9f423e42a13edd, 0x5ecd937193bc715e, 0x13b1a297a2269713, 0xa6a204f50457f5a6, 0xb901b868b86968b9, 0x0000000000000000, 0xc1b5742c74992cc1, 0x40e0a060a0806040, 0xe3c2211f21dd1fe3, 0x793a43c843f2c879, 0xb69a2ced2c77edb6, 0xd40dd9bed9b3bed4, 0x8d47ca46ca01468d, 0x671770d970ced967, 0x72afdd4bdde44b72, 0x94ed79de7933de94, 0x98ff67d4672bd498, 0xb09323e8237be8b0, 0x855bde4ade114a85, 0xbb06bd6bbd6d6bbb, 0xc5bb7e2a7e912ac5, 0x4f7b34e5349ee54f, 0xedd73a163ac116ed, 0x86d254c55417c586, 0x9af862d7622fd79a, 0x6699ff55ffcc5566, 0x11b6a794a7229411, 0x8ac04acf4a0fcf8a, 0xe9d9301030c910e9, 0x040e0a060a080604, 0xfe66988198e781fe, 0xa0ab0bf00b5bf0a0, 0x78b4cc44ccf04478, 0x25f0d5bad54aba25, 0x4b753ee33e96e34b, 0xa2ac0ef30e5ff3a2, 0x5d4419fe19bafe5d, 0x80db5bc05b1bc080, 0x0580858a850a8a05, 0x3fd3ecadec7ead3f, 0x21fedfbcdf42bc21, 0x70a8d848d8e04870, 0xf1fd0c040cf904f1, 0x63197adf7ac6df63, 0x772f58c158eec177, 0xaf309f759f4575af, 0x42e7a563a5846342, 0x2070503050403020, 0xe5cb2e1a2ed11ae5, 0xfdef120e12e10efd, 0xbf08b76db7656dbf, 0x8155d44cd4194c81, 0x18243c143c301418, 0x26795f355f4c3526, 0xc3b2712f719d2fc3, 0xbe8638e13867e1be, 0x35c8fda2fd6aa235, 0x88c74fcc4f0bcc88, 0x2e654b394b5c392e, 0x936af957f93d5793, 0x55580df20daaf255, 0xfc619d829de382fc, 0x7ab3c947c9f4477a, 0xc827efacef8bacc8, 0xba8832e7326fe7ba, 0x324f7d2b7d642b32, 0xe642a495a4d795e6, 0xc03bfba0fb9ba0c0, 0x19aab398b3329819, 0x9ef668d16827d19e, 0xa322817f815d7fa3, 0x44eeaa66aa886644, 0x54d6827e82a87e54, 0x3bdde6abe676ab3b, 0x0b959e839e16830b, 0x8cc945ca4503ca8c, 0xc7bc7b297b9529c7, 0x6b056ed36ed6d36b, 0x286c443c44503c28, 0xa72c8b798b5579a7, 0xbc813de23d63e2bc, 0x1631271d272c1d16, 0xad379a769a4176ad, 0xdb964d3b4dad3bdb, 0x649efa56fac85664, 0x74a6d24ed2e84e74, 0x1436221e22281e14, 0x92e476db763fdb92, 0x0c121e0a1e180a0c, 0x48fcb46cb4906c48, 0xb88f37e4376be4b8, 0x9f78e75de7255d9f, 0xbd0fb26eb2616ebd, 0x43692aef2a86ef43, 0xc435f1a6f193a6c4, 0x39dae3a8e372a839, 0x31c6f7a4f762a431, 0xd38a593759bd37d3, 0xf274868b86ff8bf2, 0xd583563256b132d5, 0x8b4ec543c50d438b, 0x6e85eb59ebdc596e, 0xda18c2b7c2afb7da, 0x018e8f8c8f028c01, 0xb11dac64ac7964b1, 0x9cf16dd26d23d29c, 0x49723be03b92e049, 0xd81fc7b4c7abb4d8, 0xacb915fa1543faac, 0xf3fa090709fd07f3, 0xcfa06f256f8525cf, 0xca20eaafea8fafca, 0xf47d898e89f38ef4, 0x476720e9208ee947, 0x1038281828201810, 0x6f0b64d564ded56f, 0xf073838883fb88f0, 0x4afbb16fb1946f4a, 0x5cca967296b8725c, 0x38546c246c702438, 0x575f08f108aef157, 0x732152c752e6c773, 0x9764f351f3355197, 0xcbae6523658d23cb, 0xa125847c84597ca1, 0xe857bf9cbfcb9ce8, 0x3e5d6321637c213e, 0x96ea7cdd7c37dd96, 0x611e7fdc7fc2dc61, 0x0d9c9186911a860d, 0x0f9b9485941e850f, 0xe04bab90abdb90e0, 0x7cbac642c6f8427c, 0x712657c457e2c471, 0xcc29e5aae583aacc, 0x90e373d8733bd890, 0x06090f050f0c0506, 0xf7f4030103f501f7, 0x1c2a36123638121c, 0xc23cfea3fe9fa3c2, 0x6a8be15fe1d45f6a, 0xaebe10f91047f9ae, 0x69026bd06bd2d069, 0x17bfa891a82e9117, 0x9971e858e8295899, 0x3a5369276974273a, 0x27f7d0b9d04eb927, 0xd991483848a938d9, 0xebde351335cd13eb, 0x2be5ceb3ce56b32b, 0x2277553355443322, 0xd204d6bbd6bfbbd2, 0xa9399070904970a9, 0x07878089800e8907, 0x33c1f2a7f266a733, 0x2decc1b6c15ab62d, 0x3c5a66226678223c, 0x15b8ad92ad2a9215, 0xc9a96020608920c9, 0x875cdb49db154987, 0xaab01aff1a4fffaa, 0x50d8887888a07850, 0xa52b8e7a8e517aa5, 0x03898a8f8a068f03, 0x594a13f813b2f859, 0x09929b809b128009, 0x1a2339173934171a, 0x651075da75cada65, 0xd784533153b531d7, 0x84d551c65113c684, 0xd003d3b8d3bbb8d0, 0x82dc5ec35e1fc382, 0x29e2cbb0cb52b029, 0x5ac3997799b4775a, 0x1e2d3311333c111e, 0x7b3d46cb46f6cb7b, 0xa8b71ffc1f4bfca8, 0x6d0c61d661dad66d, 0x2c624e3a4e583a2c], + [0xc6c632f4a5f497a5, 0xf8f86f978497eb84, 0xeeee5eb099b0c799, 0xf6f67a8c8d8cf78d, 0xffffe8170d17e50d, 0xd6d60adcbddcb7bd, 0xdede16c8b1c8a7b1, 0x91916dfc54fc3954, 0x606090f050f0c050, 0x0202070503050403, 0xcece2ee0a9e087a9, 0x5656d1877d87ac7d, 0xe7e7cc2b192bd519, 0xb5b513a662a67162, 0x4d4d7c31e6319ae6, 0xecec59b59ab5c39a, 0x8f8f40cf45cf0545, 0x1f1fa3bc9dbc3e9d, 0x898949c040c00940, 0xfafa68928792ef87, 0xefefd03f153fc515, 0xb2b29426eb267feb, 0x8e8ece40c94007c9, 0xfbfbe61d0b1ded0b, 0x41416e2fec2f82ec, 0xb3b31aa967a97d67, 0x5f5f431cfd1cbefd, 0x45456025ea258aea, 0x2323f9dabfda46bf, 0x53535102f702a6f7, 0xe4e445a196a1d396, 0x9b9b76ed5bed2d5b, 0x7575285dc25deac2, 0xe1e1c5241c24d91c, 0x3d3dd4e9aee97aae, 0x4c4cf2be6abe986a, 0x6c6c82ee5aeed85a, 0x7e7ebdc341c3fc41, 0xf5f5f3060206f102, 0x838352d14fd11d4f, 0x68688ce45ce4d05c, 0x51515607f407a2f4, 0xd1d18d5c345cb934, 0xf9f9e1180818e908, 0xe2e24cae93aedf93, 0xabab3e9573954d73, 0x626297f553f5c453, 0x2a2a6b413f41543f, 0x08081c140c14100c, 0x959563f652f63152, 0x4646e9af65af8c65, 0x9d9d7fe25ee2215e, 0x3030487828786028, 0x3737cff8a1f86ea1, 0x0a0a1b110f11140f, 0x2f2febc4b5c45eb5, 0x0e0e151b091b1c09, 0x24247e5a365a4836, 0x1b1badb69bb6369b, 0xdfdf98473d47a53d, 0xcdcda76a266a8126, 0x4e4ef5bb69bb9c69, 0x7f7f334ccd4cfecd, 0xeaea50ba9fbacf9f, 0x12123f2d1b2d241b, 0x1d1da4b99eb93a9e, 0x5858c49c749cb074, 0x343446722e72682e, 0x363641772d776c2d, 0xdcdc11cdb2cda3b2, 0xb4b49d29ee2973ee, 0x5b5b4d16fb16b6fb, 0xa4a4a501f60153f6, 0x7676a1d74dd7ec4d, 0xb7b714a361a37561, 0x7d7d3449ce49face, 0x5252df8d7b8da47b, 0xdddd9f423e42a13e, 0x5e5ecd937193bc71, 0x1313b1a297a22697, 0xa6a6a204f50457f5, 0xb9b901b868b86968, 0x0000000000000000, 0xc1c1b5742c74992c, 0x4040e0a060a08060, 0xe3e3c2211f21dd1f, 0x79793a43c843f2c8, 0xb6b69a2ced2c77ed, 0xd4d40dd9bed9b3be, 0x8d8d47ca46ca0146, 0x67671770d970ced9, 0x7272afdd4bdde44b, 0x9494ed79de7933de, 0x9898ff67d4672bd4, 0xb0b09323e8237be8, 0x85855bde4ade114a, 0xbbbb06bd6bbd6d6b, 0xc5c5bb7e2a7e912a, 0x4f4f7b34e5349ee5, 0xededd73a163ac116, 0x8686d254c55417c5, 0x9a9af862d7622fd7, 0x666699ff55ffcc55, 0x1111b6a794a72294, 0x8a8ac04acf4a0fcf, 0xe9e9d9301030c910, 0x04040e0a060a0806, 0xfefe66988198e781, 0xa0a0ab0bf00b5bf0, 0x7878b4cc44ccf044, 0x2525f0d5bad54aba, 0x4b4b753ee33e96e3, 0xa2a2ac0ef30e5ff3, 0x5d5d4419fe19bafe, 0x8080db5bc05b1bc0, 0x050580858a850a8a, 0x3f3fd3ecadec7ead, 0x2121fedfbcdf42bc, 0x7070a8d848d8e048, 0xf1f1fd0c040cf904, 0x6363197adf7ac6df, 0x77772f58c158eec1, 0xafaf309f759f4575, 0x4242e7a563a58463, 0x2020705030504030, 0xe5e5cb2e1a2ed11a, 0xfdfdef120e12e10e, 0xbfbf08b76db7656d, 0x818155d44cd4194c, 0x1818243c143c3014, 0x2626795f355f4c35, 0xc3c3b2712f719d2f, 0xbebe8638e13867e1, 0x3535c8fda2fd6aa2, 0x8888c74fcc4f0bcc, 0x2e2e654b394b5c39, 0x93936af957f93d57, 0x5555580df20daaf2, 0xfcfc619d829de382, 0x7a7ab3c947c9f447, 0xc8c827efacef8bac, 0xbaba8832e7326fe7, 0x32324f7d2b7d642b, 0xe6e642a495a4d795, 0xc0c03bfba0fb9ba0, 0x1919aab398b33298, 0x9e9ef668d16827d1, 0xa3a322817f815d7f, 0x4444eeaa66aa8866, 0x5454d6827e82a87e, 0x3b3bdde6abe676ab, 0x0b0b959e839e1683, 0x8c8cc945ca4503ca, 0xc7c7bc7b297b9529, 0x6b6b056ed36ed6d3, 0x28286c443c44503c, 0xa7a72c8b798b5579, 0xbcbc813de23d63e2, 0x161631271d272c1d, 0xadad379a769a4176, 0xdbdb964d3b4dad3b, 0x64649efa56fac856, 0x7474a6d24ed2e84e, 0x141436221e22281e, 0x9292e476db763fdb, 0x0c0c121e0a1e180a, 0x4848fcb46cb4906c, 0xb8b88f37e4376be4, 0x9f9f78e75de7255d, 0xbdbd0fb26eb2616e, 0x4343692aef2a86ef, 0xc4c435f1a6f193a6, 0x3939dae3a8e372a8, 0x3131c6f7a4f762a4, 0xd3d38a593759bd37, 0xf2f274868b86ff8b, 0xd5d583563256b132, 0x8b8b4ec543c50d43, 0x6e6e85eb59ebdc59, 0xdada18c2b7c2afb7, 0x01018e8f8c8f028c, 0xb1b11dac64ac7964, 0x9c9cf16dd26d23d2, 0x4949723be03b92e0, 0xd8d81fc7b4c7abb4, 0xacacb915fa1543fa, 0xf3f3fa090709fd07, 0xcfcfa06f256f8525, 0xcaca20eaafea8faf, 0xf4f47d898e89f38e, 0x47476720e9208ee9, 0x1010382818282018, 0x6f6f0b64d564ded5, 0xf0f073838883fb88, 0x4a4afbb16fb1946f, 0x5c5cca967296b872, 0x3838546c246c7024, 0x57575f08f108aef1, 0x73732152c752e6c7, 0x979764f351f33551, 0xcbcbae6523658d23, 0xa1a125847c84597c, 0xe8e857bf9cbfcb9c, 0x3e3e5d6321637c21, 0x9696ea7cdd7c37dd, 0x61611e7fdc7fc2dc, 0x0d0d9c9186911a86, 0x0f0f9b9485941e85, 0xe0e04bab90abdb90, 0x7c7cbac642c6f842, 0x71712657c457e2c4, 0xcccc29e5aae583aa, 0x9090e373d8733bd8, 0x0606090f050f0c05, 0xf7f7f4030103f501, 0x1c1c2a3612363812, 0xc2c23cfea3fe9fa3, 0x6a6a8be15fe1d45f, 0xaeaebe10f91047f9, 0x6969026bd06bd2d0, 0x1717bfa891a82e91, 0x999971e858e82958, 0x3a3a536927697427, 0x2727f7d0b9d04eb9, 0xd9d991483848a938, 0xebebde351335cd13, 0x2b2be5ceb3ce56b3, 0x2222775533554433, 0xd2d204d6bbd6bfbb, 0xa9a9399070904970, 0x0707878089800e89, 0x3333c1f2a7f266a7, 0x2d2decc1b6c15ab6, 0x3c3c5a6622667822, 0x1515b8ad92ad2a92, 0xc9c9a96020608920, 0x87875cdb49db1549, 0xaaaab01aff1a4fff, 0x5050d8887888a078, 0xa5a52b8e7a8e517a, 0x0303898a8f8a068f, 0x59594a13f813b2f8, 0x0909929b809b1280, 0x1a1a233917393417, 0x65651075da75cada, 0xd7d784533153b531, 0x8484d551c65113c6, 0xd0d003d3b8d3bbb8, 0x8282dc5ec35e1fc3, 0x2929e2cbb0cb52b0, 0x5a5ac3997799b477, 0x1e1e2d3311333c11, 0x7b7b3d46cb46f6cb, 0xa8a8b71ffc1f4bfc, 0x6d6d0c61d661dad6, 0x2c2c624e3a4e583a], + [0xa5c6c632f4a5f497, 0x84f8f86f978497eb, 0x99eeee5eb099b0c7, 0x8df6f67a8c8d8cf7, 0x0dffffe8170d17e5, 0xbdd6d60adcbddcb7, 0xb1dede16c8b1c8a7, 0x5491916dfc54fc39, 0x50606090f050f0c0, 0x0302020705030504, 0xa9cece2ee0a9e087, 0x7d5656d1877d87ac, 0x19e7e7cc2b192bd5, 0x62b5b513a662a671, 0xe64d4d7c31e6319a, 0x9aecec59b59ab5c3, 0x458f8f40cf45cf05, 0x9d1f1fa3bc9dbc3e, 0x40898949c040c009, 0x87fafa68928792ef, 0x15efefd03f153fc5, 0xebb2b29426eb267f, 0xc98e8ece40c94007, 0x0bfbfbe61d0b1ded, 0xec41416e2fec2f82, 0x67b3b31aa967a97d, 0xfd5f5f431cfd1cbe, 0xea45456025ea258a, 0xbf2323f9dabfda46, 0xf753535102f702a6, 0x96e4e445a196a1d3, 0x5b9b9b76ed5bed2d, 0xc27575285dc25dea, 0x1ce1e1c5241c24d9, 0xae3d3dd4e9aee97a, 0x6a4c4cf2be6abe98, 0x5a6c6c82ee5aeed8, 0x417e7ebdc341c3fc, 0x02f5f5f3060206f1, 0x4f838352d14fd11d, 0x5c68688ce45ce4d0, 0xf451515607f407a2, 0x34d1d18d5c345cb9, 0x08f9f9e1180818e9, 0x93e2e24cae93aedf, 0x73abab3e9573954d, 0x53626297f553f5c4, 0x3f2a2a6b413f4154, 0x0c08081c140c1410, 0x52959563f652f631, 0x654646e9af65af8c, 0x5e9d9d7fe25ee221, 0x2830304878287860, 0xa13737cff8a1f86e, 0x0f0a0a1b110f1114, 0xb52f2febc4b5c45e, 0x090e0e151b091b1c, 0x3624247e5a365a48, 0x9b1b1badb69bb636, 0x3ddfdf98473d47a5, 0x26cdcda76a266a81, 0x694e4ef5bb69bb9c, 0xcd7f7f334ccd4cfe, 0x9feaea50ba9fbacf, 0x1b12123f2d1b2d24, 0x9e1d1da4b99eb93a, 0x745858c49c749cb0, 0x2e343446722e7268, 0x2d363641772d776c, 0xb2dcdc11cdb2cda3, 0xeeb4b49d29ee2973, 0xfb5b5b4d16fb16b6, 0xf6a4a4a501f60153, 0x4d7676a1d74dd7ec, 0x61b7b714a361a375, 0xce7d7d3449ce49fa, 0x7b5252df8d7b8da4, 0x3edddd9f423e42a1, 0x715e5ecd937193bc, 0x971313b1a297a226, 0xf5a6a6a204f50457, 0x68b9b901b868b869, 0x0000000000000000, 0x2cc1c1b5742c7499, 0x604040e0a060a080, 0x1fe3e3c2211f21dd, 0xc879793a43c843f2, 0xedb6b69a2ced2c77, 0xbed4d40dd9bed9b3, 0x468d8d47ca46ca01, 0xd967671770d970ce, 0x4b7272afdd4bdde4, 0xde9494ed79de7933, 0xd49898ff67d4672b, 0xe8b0b09323e8237b, 0x4a85855bde4ade11, 0x6bbbbb06bd6bbd6d, 0x2ac5c5bb7e2a7e91, 0xe54f4f7b34e5349e, 0x16ededd73a163ac1, 0xc58686d254c55417, 0xd79a9af862d7622f, 0x55666699ff55ffcc, 0x941111b6a794a722, 0xcf8a8ac04acf4a0f, 0x10e9e9d9301030c9, 0x0604040e0a060a08, 0x81fefe66988198e7, 0xf0a0a0ab0bf00b5b, 0x447878b4cc44ccf0, 0xba2525f0d5bad54a, 0xe34b4b753ee33e96, 0xf3a2a2ac0ef30e5f, 0xfe5d5d4419fe19ba, 0xc08080db5bc05b1b, 0x8a050580858a850a, 0xad3f3fd3ecadec7e, 0xbc2121fedfbcdf42, 0x487070a8d848d8e0, 0x04f1f1fd0c040cf9, 0xdf6363197adf7ac6, 0xc177772f58c158ee, 0x75afaf309f759f45, 0x634242e7a563a584, 0x3020207050305040, 0x1ae5e5cb2e1a2ed1, 0x0efdfdef120e12e1, 0x6dbfbf08b76db765, 0x4c818155d44cd419, 0x141818243c143c30, 0x352626795f355f4c, 0x2fc3c3b2712f719d, 0xe1bebe8638e13867, 0xa23535c8fda2fd6a, 0xcc8888c74fcc4f0b, 0x392e2e654b394b5c, 0x5793936af957f93d, 0xf25555580df20daa, 0x82fcfc619d829de3, 0x477a7ab3c947c9f4, 0xacc8c827efacef8b, 0xe7baba8832e7326f, 0x2b32324f7d2b7d64, 0x95e6e642a495a4d7, 0xa0c0c03bfba0fb9b, 0x981919aab398b332, 0xd19e9ef668d16827, 0x7fa3a322817f815d, 0x664444eeaa66aa88, 0x7e5454d6827e82a8, 0xab3b3bdde6abe676, 0x830b0b959e839e16, 0xca8c8cc945ca4503, 0x29c7c7bc7b297b95, 0xd36b6b056ed36ed6, 0x3c28286c443c4450, 0x79a7a72c8b798b55, 0xe2bcbc813de23d63, 0x1d161631271d272c, 0x76adad379a769a41, 0x3bdbdb964d3b4dad, 0x5664649efa56fac8, 0x4e7474a6d24ed2e8, 0x1e141436221e2228, 0xdb9292e476db763f, 0x0a0c0c121e0a1e18, 0x6c4848fcb46cb490, 0xe4b8b88f37e4376b, 0x5d9f9f78e75de725, 0x6ebdbd0fb26eb261, 0xef4343692aef2a86, 0xa6c4c435f1a6f193, 0xa83939dae3a8e372, 0xa43131c6f7a4f762, 0x37d3d38a593759bd, 0x8bf2f274868b86ff, 0x32d5d583563256b1, 0x438b8b4ec543c50d, 0x596e6e85eb59ebdc, 0xb7dada18c2b7c2af, 0x8c01018e8f8c8f02, 0x64b1b11dac64ac79, 0xd29c9cf16dd26d23, 0xe04949723be03b92, 0xb4d8d81fc7b4c7ab, 0xfaacacb915fa1543, 0x07f3f3fa090709fd, 0x25cfcfa06f256f85, 0xafcaca20eaafea8f, 0x8ef4f47d898e89f3, 0xe947476720e9208e, 0x1810103828182820, 0xd56f6f0b64d564de, 0x88f0f073838883fb, 0x6f4a4afbb16fb194, 0x725c5cca967296b8, 0x243838546c246c70, 0xf157575f08f108ae, 0xc773732152c752e6, 0x51979764f351f335, 0x23cbcbae6523658d, 0x7ca1a125847c8459, 0x9ce8e857bf9cbfcb, 0x213e3e5d6321637c, 0xdd9696ea7cdd7c37, 0xdc61611e7fdc7fc2, 0x860d0d9c9186911a, 0x850f0f9b9485941e, 0x90e0e04bab90abdb, 0x427c7cbac642c6f8, 0xc471712657c457e2, 0xaacccc29e5aae583, 0xd89090e373d8733b, 0x050606090f050f0c, 0x01f7f7f4030103f5, 0x121c1c2a36123638, 0xa3c2c23cfea3fe9f, 0x5f6a6a8be15fe1d4, 0xf9aeaebe10f91047, 0xd06969026bd06bd2, 0x911717bfa891a82e, 0x58999971e858e829, 0x273a3a5369276974, 0xb92727f7d0b9d04e, 0x38d9d991483848a9, 0x13ebebde351335cd, 0xb32b2be5ceb3ce56, 0x3322227755335544, 0xbbd2d204d6bbd6bf, 0x70a9a93990709049, 0x890707878089800e, 0xa73333c1f2a7f266, 0xb62d2decc1b6c15a, 0x223c3c5a66226678, 0x921515b8ad92ad2a, 0x20c9c9a960206089, 0x4987875cdb49db15, 0xffaaaab01aff1a4f, 0x785050d8887888a0, 0x7aa5a52b8e7a8e51, 0x8f0303898a8f8a06, 0xf859594a13f813b2, 0x800909929b809b12, 0x171a1a2339173934, 0xda65651075da75ca, 0x31d7d784533153b5, 0xc68484d551c65113, 0xb8d0d003d3b8d3bb, 0xc38282dc5ec35e1f, 0xb02929e2cbb0cb52, 0x775a5ac3997799b4, 0x111e1e2d3311333c, 0xcb7b7b3d46cb46f6, 0xfca8a8b71ffc1f4b, 0xd66d6d0c61d661da, 0x3a2c2c624e3a4e58], + [0x97a5c6c632f4a5f4, 0xeb84f8f86f978497, 0xc799eeee5eb099b0, 0xf78df6f67a8c8d8c, 0xe50dffffe8170d17, 0xb7bdd6d60adcbddc, 0xa7b1dede16c8b1c8, 0x395491916dfc54fc, 0xc050606090f050f0, 0x0403020207050305, 0x87a9cece2ee0a9e0, 0xac7d5656d1877d87, 0xd519e7e7cc2b192b, 0x7162b5b513a662a6, 0x9ae64d4d7c31e631, 0xc39aecec59b59ab5, 0x05458f8f40cf45cf, 0x3e9d1f1fa3bc9dbc, 0x0940898949c040c0, 0xef87fafa68928792, 0xc515efefd03f153f, 0x7febb2b29426eb26, 0x07c98e8ece40c940, 0xed0bfbfbe61d0b1d, 0x82ec41416e2fec2f, 0x7d67b3b31aa967a9, 0xbefd5f5f431cfd1c, 0x8aea45456025ea25, 0x46bf2323f9dabfda, 0xa6f753535102f702, 0xd396e4e445a196a1, 0x2d5b9b9b76ed5bed, 0xeac27575285dc25d, 0xd91ce1e1c5241c24, 0x7aae3d3dd4e9aee9, 0x986a4c4cf2be6abe, 0xd85a6c6c82ee5aee, 0xfc417e7ebdc341c3, 0xf102f5f5f3060206, 0x1d4f838352d14fd1, 0xd05c68688ce45ce4, 0xa2f451515607f407, 0xb934d1d18d5c345c, 0xe908f9f9e1180818, 0xdf93e2e24cae93ae, 0x4d73abab3e957395, 0xc453626297f553f5, 0x543f2a2a6b413f41, 0x100c08081c140c14, 0x3152959563f652f6, 0x8c654646e9af65af, 0x215e9d9d7fe25ee2, 0x6028303048782878, 0x6ea13737cff8a1f8, 0x140f0a0a1b110f11, 0x5eb52f2febc4b5c4, 0x1c090e0e151b091b, 0x483624247e5a365a, 0x369b1b1badb69bb6, 0xa53ddfdf98473d47, 0x8126cdcda76a266a, 0x9c694e4ef5bb69bb, 0xfecd7f7f334ccd4c, 0xcf9feaea50ba9fba, 0x241b12123f2d1b2d, 0x3a9e1d1da4b99eb9, 0xb0745858c49c749c, 0x682e343446722e72, 0x6c2d363641772d77, 0xa3b2dcdc11cdb2cd, 0x73eeb4b49d29ee29, 0xb6fb5b5b4d16fb16, 0x53f6a4a4a501f601, 0xec4d7676a1d74dd7, 0x7561b7b714a361a3, 0xface7d7d3449ce49, 0xa47b5252df8d7b8d, 0xa13edddd9f423e42, 0xbc715e5ecd937193, 0x26971313b1a297a2, 0x57f5a6a6a204f504, 0x6968b9b901b868b8, 0x0000000000000000, 0x992cc1c1b5742c74, 0x80604040e0a060a0, 0xdd1fe3e3c2211f21, 0xf2c879793a43c843, 0x77edb6b69a2ced2c, 0xb3bed4d40dd9bed9, 0x01468d8d47ca46ca, 0xced967671770d970, 0xe44b7272afdd4bdd, 0x33de9494ed79de79, 0x2bd49898ff67d467, 0x7be8b0b09323e823, 0x114a85855bde4ade, 0x6d6bbbbb06bd6bbd, 0x912ac5c5bb7e2a7e, 0x9ee54f4f7b34e534, 0xc116ededd73a163a, 0x17c58686d254c554, 0x2fd79a9af862d762, 0xcc55666699ff55ff, 0x22941111b6a794a7, 0x0fcf8a8ac04acf4a, 0xc910e9e9d9301030, 0x080604040e0a060a, 0xe781fefe66988198, 0x5bf0a0a0ab0bf00b, 0xf0447878b4cc44cc, 0x4aba2525f0d5bad5, 0x96e34b4b753ee33e, 0x5ff3a2a2ac0ef30e, 0xbafe5d5d4419fe19, 0x1bc08080db5bc05b, 0x0a8a050580858a85, 0x7ead3f3fd3ecadec, 0x42bc2121fedfbcdf, 0xe0487070a8d848d8, 0xf904f1f1fd0c040c, 0xc6df6363197adf7a, 0xeec177772f58c158, 0x4575afaf309f759f, 0x84634242e7a563a5, 0x4030202070503050, 0xd11ae5e5cb2e1a2e, 0xe10efdfdef120e12, 0x656dbfbf08b76db7, 0x194c818155d44cd4, 0x30141818243c143c, 0x4c352626795f355f, 0x9d2fc3c3b2712f71, 0x67e1bebe8638e138, 0x6aa23535c8fda2fd, 0x0bcc8888c74fcc4f, 0x5c392e2e654b394b, 0x3d5793936af957f9, 0xaaf25555580df20d, 0xe382fcfc619d829d, 0xf4477a7ab3c947c9, 0x8bacc8c827efacef, 0x6fe7baba8832e732, 0x642b32324f7d2b7d, 0xd795e6e642a495a4, 0x9ba0c0c03bfba0fb, 0x32981919aab398b3, 0x27d19e9ef668d168, 0x5d7fa3a322817f81, 0x88664444eeaa66aa, 0xa87e5454d6827e82, 0x76ab3b3bdde6abe6, 0x16830b0b959e839e, 0x03ca8c8cc945ca45, 0x9529c7c7bc7b297b, 0xd6d36b6b056ed36e, 0x503c28286c443c44, 0x5579a7a72c8b798b, 0x63e2bcbc813de23d, 0x2c1d161631271d27, 0x4176adad379a769a, 0xad3bdbdb964d3b4d, 0xc85664649efa56fa, 0xe84e7474a6d24ed2, 0x281e141436221e22, 0x3fdb9292e476db76, 0x180a0c0c121e0a1e, 0x906c4848fcb46cb4, 0x6be4b8b88f37e437, 0x255d9f9f78e75de7, 0x616ebdbd0fb26eb2, 0x86ef4343692aef2a, 0x93a6c4c435f1a6f1, 0x72a83939dae3a8e3, 0x62a43131c6f7a4f7, 0xbd37d3d38a593759, 0xff8bf2f274868b86, 0xb132d5d583563256, 0x0d438b8b4ec543c5, 0xdc596e6e85eb59eb, 0xafb7dada18c2b7c2, 0x028c01018e8f8c8f, 0x7964b1b11dac64ac, 0x23d29c9cf16dd26d, 0x92e04949723be03b, 0xabb4d8d81fc7b4c7, 0x43faacacb915fa15, 0xfd07f3f3fa090709, 0x8525cfcfa06f256f, 0x8fafcaca20eaafea, 0xf38ef4f47d898e89, 0x8ee947476720e920, 0x2018101038281828, 0xded56f6f0b64d564, 0xfb88f0f073838883, 0x946f4a4afbb16fb1, 0xb8725c5cca967296, 0x70243838546c246c, 0xaef157575f08f108, 0xe6c773732152c752, 0x3551979764f351f3, 0x8d23cbcbae652365, 0x597ca1a125847c84, 0xcb9ce8e857bf9cbf, 0x7c213e3e5d632163, 0x37dd9696ea7cdd7c, 0xc2dc61611e7fdc7f, 0x1a860d0d9c918691, 0x1e850f0f9b948594, 0xdb90e0e04bab90ab, 0xf8427c7cbac642c6, 0xe2c471712657c457, 0x83aacccc29e5aae5, 0x3bd89090e373d873, 0x0c050606090f050f, 0xf501f7f7f4030103, 0x38121c1c2a361236, 0x9fa3c2c23cfea3fe, 0xd45f6a6a8be15fe1, 0x47f9aeaebe10f910, 0xd2d06969026bd06b, 0x2e911717bfa891a8, 0x2958999971e858e8, 0x74273a3a53692769, 0x4eb92727f7d0b9d0, 0xa938d9d991483848, 0xcd13ebebde351335, 0x56b32b2be5ceb3ce, 0x4433222277553355, 0xbfbbd2d204d6bbd6, 0x4970a9a939907090, 0x0e89070787808980, 0x66a73333c1f2a7f2, 0x5ab62d2decc1b6c1, 0x78223c3c5a662266, 0x2a921515b8ad92ad, 0x8920c9c9a9602060, 0x154987875cdb49db, 0x4fffaaaab01aff1a, 0xa0785050d8887888, 0x517aa5a52b8e7a8e, 0x068f0303898a8f8a, 0xb2f859594a13f813, 0x12800909929b809b, 0x34171a1a23391739, 0xcada65651075da75, 0xb531d7d784533153, 0x13c68484d551c651, 0xbbb8d0d003d3b8d3, 0x1fc38282dc5ec35e, 0x52b02929e2cbb0cb, 0xb4775a5ac3997799, 0x3c111e1e2d331133, 0xf6cb7b7b3d46cb46, 0x4bfca8a8b71ffc1f, 0xdad66d6d0c61d661, 0x583a2c2c624e3a4e], + [0xf497a5c6c632f4a5, 0x97eb84f8f86f9784, 0xb0c799eeee5eb099, 0x8cf78df6f67a8c8d, 0x17e50dffffe8170d, 0xdcb7bdd6d60adcbd, 0xc8a7b1dede16c8b1, 0xfc395491916dfc54, 0xf0c050606090f050, 0x0504030202070503, 0xe087a9cece2ee0a9, 0x87ac7d5656d1877d, 0x2bd519e7e7cc2b19, 0xa67162b5b513a662, 0x319ae64d4d7c31e6, 0xb5c39aecec59b59a, 0xcf05458f8f40cf45, 0xbc3e9d1f1fa3bc9d, 0xc00940898949c040, 0x92ef87fafa689287, 0x3fc515efefd03f15, 0x267febb2b29426eb, 0x4007c98e8ece40c9, 0x1ded0bfbfbe61d0b, 0x2f82ec41416e2fec, 0xa97d67b3b31aa967, 0x1cbefd5f5f431cfd, 0x258aea45456025ea, 0xda46bf2323f9dabf, 0x02a6f753535102f7, 0xa1d396e4e445a196, 0xed2d5b9b9b76ed5b, 0x5deac27575285dc2, 0x24d91ce1e1c5241c, 0xe97aae3d3dd4e9ae, 0xbe986a4c4cf2be6a, 0xeed85a6c6c82ee5a, 0xc3fc417e7ebdc341, 0x06f102f5f5f30602, 0xd11d4f838352d14f, 0xe4d05c68688ce45c, 0x07a2f451515607f4, 0x5cb934d1d18d5c34, 0x18e908f9f9e11808, 0xaedf93e2e24cae93, 0x954d73abab3e9573, 0xf5c453626297f553, 0x41543f2a2a6b413f, 0x14100c08081c140c, 0xf63152959563f652, 0xaf8c654646e9af65, 0xe2215e9d9d7fe25e, 0x7860283030487828, 0xf86ea13737cff8a1, 0x11140f0a0a1b110f, 0xc45eb52f2febc4b5, 0x1b1c090e0e151b09, 0x5a483624247e5a36, 0xb6369b1b1badb69b, 0x47a53ddfdf98473d, 0x6a8126cdcda76a26, 0xbb9c694e4ef5bb69, 0x4cfecd7f7f334ccd, 0xbacf9feaea50ba9f, 0x2d241b12123f2d1b, 0xb93a9e1d1da4b99e, 0x9cb0745858c49c74, 0x72682e343446722e, 0x776c2d363641772d, 0xcda3b2dcdc11cdb2, 0x2973eeb4b49d29ee, 0x16b6fb5b5b4d16fb, 0x0153f6a4a4a501f6, 0xd7ec4d7676a1d74d, 0xa37561b7b714a361, 0x49face7d7d3449ce, 0x8da47b5252df8d7b, 0x42a13edddd9f423e, 0x93bc715e5ecd9371, 0xa226971313b1a297, 0x0457f5a6a6a204f5, 0xb86968b9b901b868, 0x0000000000000000, 0x74992cc1c1b5742c, 0xa080604040e0a060, 0x21dd1fe3e3c2211f, 0x43f2c879793a43c8, 0x2c77edb6b69a2ced, 0xd9b3bed4d40dd9be, 0xca01468d8d47ca46, 0x70ced967671770d9, 0xdde44b7272afdd4b, 0x7933de9494ed79de, 0x672bd49898ff67d4, 0x237be8b0b09323e8, 0xde114a85855bde4a, 0xbd6d6bbbbb06bd6b, 0x7e912ac5c5bb7e2a, 0x349ee54f4f7b34e5, 0x3ac116ededd73a16, 0x5417c58686d254c5, 0x622fd79a9af862d7, 0xffcc55666699ff55, 0xa722941111b6a794, 0x4a0fcf8a8ac04acf, 0x30c910e9e9d93010, 0x0a080604040e0a06, 0x98e781fefe669881, 0x0b5bf0a0a0ab0bf0, 0xccf0447878b4cc44, 0xd54aba2525f0d5ba, 0x3e96e34b4b753ee3, 0x0e5ff3a2a2ac0ef3, 0x19bafe5d5d4419fe, 0x5b1bc08080db5bc0, 0x850a8a050580858a, 0xec7ead3f3fd3ecad, 0xdf42bc2121fedfbc, 0xd8e0487070a8d848, 0x0cf904f1f1fd0c04, 0x7ac6df6363197adf, 0x58eec177772f58c1, 0x9f4575afaf309f75, 0xa584634242e7a563, 0x5040302020705030, 0x2ed11ae5e5cb2e1a, 0x12e10efdfdef120e, 0xb7656dbfbf08b76d, 0xd4194c818155d44c, 0x3c30141818243c14, 0x5f4c352626795f35, 0x719d2fc3c3b2712f, 0x3867e1bebe8638e1, 0xfd6aa23535c8fda2, 0x4f0bcc8888c74fcc, 0x4b5c392e2e654b39, 0xf93d5793936af957, 0x0daaf25555580df2, 0x9de382fcfc619d82, 0xc9f4477a7ab3c947, 0xef8bacc8c827efac, 0x326fe7baba8832e7, 0x7d642b32324f7d2b, 0xa4d795e6e642a495, 0xfb9ba0c0c03bfba0, 0xb332981919aab398, 0x6827d19e9ef668d1, 0x815d7fa3a322817f, 0xaa88664444eeaa66, 0x82a87e5454d6827e, 0xe676ab3b3bdde6ab, 0x9e16830b0b959e83, 0x4503ca8c8cc945ca, 0x7b9529c7c7bc7b29, 0x6ed6d36b6b056ed3, 0x44503c28286c443c, 0x8b5579a7a72c8b79, 0x3d63e2bcbc813de2, 0x272c1d161631271d, 0x9a4176adad379a76, 0x4dad3bdbdb964d3b, 0xfac85664649efa56, 0xd2e84e7474a6d24e, 0x22281e141436221e, 0x763fdb9292e476db, 0x1e180a0c0c121e0a, 0xb4906c4848fcb46c, 0x376be4b8b88f37e4, 0xe7255d9f9f78e75d, 0xb2616ebdbd0fb26e, 0x2a86ef4343692aef, 0xf193a6c4c435f1a6, 0xe372a83939dae3a8, 0xf762a43131c6f7a4, 0x59bd37d3d38a5937, 0x86ff8bf2f274868b, 0x56b132d5d5835632, 0xc50d438b8b4ec543, 0xebdc596e6e85eb59, 0xc2afb7dada18c2b7, 0x8f028c01018e8f8c, 0xac7964b1b11dac64, 0x6d23d29c9cf16dd2, 0x3b92e04949723be0, 0xc7abb4d8d81fc7b4, 0x1543faacacb915fa, 0x09fd07f3f3fa0907, 0x6f8525cfcfa06f25, 0xea8fafcaca20eaaf, 0x89f38ef4f47d898e, 0x208ee947476720e9, 0x2820181010382818, 0x64ded56f6f0b64d5, 0x83fb88f0f0738388, 0xb1946f4a4afbb16f, 0x96b8725c5cca9672, 0x6c70243838546c24, 0x08aef157575f08f1, 0x52e6c773732152c7, 0xf33551979764f351, 0x658d23cbcbae6523, 0x84597ca1a125847c, 0xbfcb9ce8e857bf9c, 0x637c213e3e5d6321, 0x7c37dd9696ea7cdd, 0x7fc2dc61611e7fdc, 0x911a860d0d9c9186, 0x941e850f0f9b9485, 0xabdb90e0e04bab90, 0xc6f8427c7cbac642, 0x57e2c471712657c4, 0xe583aacccc29e5aa, 0x733bd89090e373d8, 0x0f0c050606090f05, 0x03f501f7f7f40301, 0x3638121c1c2a3612, 0xfe9fa3c2c23cfea3, 0xe1d45f6a6a8be15f, 0x1047f9aeaebe10f9, 0x6bd2d06969026bd0, 0xa82e911717bfa891, 0xe82958999971e858, 0x6974273a3a536927, 0xd04eb92727f7d0b9, 0x48a938d9d9914838, 0x35cd13ebebde3513, 0xce56b32b2be5ceb3, 0x5544332222775533, 0xd6bfbbd2d204d6bb, 0x904970a9a9399070, 0x800e890707878089, 0xf266a73333c1f2a7, 0xc15ab62d2decc1b6, 0x6678223c3c5a6622, 0xad2a921515b8ad92, 0x608920c9c9a96020, 0xdb154987875cdb49, 0x1a4fffaaaab01aff, 0x88a0785050d88878, 0x8e517aa5a52b8e7a, 0x8a068f0303898a8f, 0x13b2f859594a13f8, 0x9b12800909929b80, 0x3934171a1a233917, 0x75cada65651075da, 0x53b531d7d7845331, 0x5113c68484d551c6, 0xd3bbb8d0d003d3b8, 0x5e1fc38282dc5ec3, 0xcb52b02929e2cbb0, 0x99b4775a5ac39977, 0x333c111e1e2d3311, 0x46f6cb7b7b3d46cb, 0x1f4bfca8a8b71ffc, 0x61dad66d6d0c61d6, 0x4e583a2c2c624e3a], + [0xa5f497a5c6c632f4, 0x8497eb84f8f86f97, 0x99b0c799eeee5eb0, 0x8d8cf78df6f67a8c, 0x0d17e50dffffe817, 0xbddcb7bdd6d60adc, 0xb1c8a7b1dede16c8, 0x54fc395491916dfc, 0x50f0c050606090f0, 0x0305040302020705, 0xa9e087a9cece2ee0, 0x7d87ac7d5656d187, 0x192bd519e7e7cc2b, 0x62a67162b5b513a6, 0xe6319ae64d4d7c31, 0x9ab5c39aecec59b5, 0x45cf05458f8f40cf, 0x9dbc3e9d1f1fa3bc, 0x40c00940898949c0, 0x8792ef87fafa6892, 0x153fc515efefd03f, 0xeb267febb2b29426, 0xc94007c98e8ece40, 0x0b1ded0bfbfbe61d, 0xec2f82ec41416e2f, 0x67a97d67b3b31aa9, 0xfd1cbefd5f5f431c, 0xea258aea45456025, 0xbfda46bf2323f9da, 0xf702a6f753535102, 0x96a1d396e4e445a1, 0x5bed2d5b9b9b76ed, 0xc25deac27575285d, 0x1c24d91ce1e1c524, 0xaee97aae3d3dd4e9, 0x6abe986a4c4cf2be, 0x5aeed85a6c6c82ee, 0x41c3fc417e7ebdc3, 0x0206f102f5f5f306, 0x4fd11d4f838352d1, 0x5ce4d05c68688ce4, 0xf407a2f451515607, 0x345cb934d1d18d5c, 0x0818e908f9f9e118, 0x93aedf93e2e24cae, 0x73954d73abab3e95, 0x53f5c453626297f5, 0x3f41543f2a2a6b41, 0x0c14100c08081c14, 0x52f63152959563f6, 0x65af8c654646e9af, 0x5ee2215e9d9d7fe2, 0x2878602830304878, 0xa1f86ea13737cff8, 0x0f11140f0a0a1b11, 0xb5c45eb52f2febc4, 0x091b1c090e0e151b, 0x365a483624247e5a, 0x9bb6369b1b1badb6, 0x3d47a53ddfdf9847, 0x266a8126cdcda76a, 0x69bb9c694e4ef5bb, 0xcd4cfecd7f7f334c, 0x9fbacf9feaea50ba, 0x1b2d241b12123f2d, 0x9eb93a9e1d1da4b9, 0x749cb0745858c49c, 0x2e72682e34344672, 0x2d776c2d36364177, 0xb2cda3b2dcdc11cd, 0xee2973eeb4b49d29, 0xfb16b6fb5b5b4d16, 0xf60153f6a4a4a501, 0x4dd7ec4d7676a1d7, 0x61a37561b7b714a3, 0xce49face7d7d3449, 0x7b8da47b5252df8d, 0x3e42a13edddd9f42, 0x7193bc715e5ecd93, 0x97a226971313b1a2, 0xf50457f5a6a6a204, 0x68b86968b9b901b8, 0x0000000000000000, 0x2c74992cc1c1b574, 0x60a080604040e0a0, 0x1f21dd1fe3e3c221, 0xc843f2c879793a43, 0xed2c77edb6b69a2c, 0xbed9b3bed4d40dd9, 0x46ca01468d8d47ca, 0xd970ced967671770, 0x4bdde44b7272afdd, 0xde7933de9494ed79, 0xd4672bd49898ff67, 0xe8237be8b0b09323, 0x4ade114a85855bde, 0x6bbd6d6bbbbb06bd, 0x2a7e912ac5c5bb7e, 0xe5349ee54f4f7b34, 0x163ac116ededd73a, 0xc55417c58686d254, 0xd7622fd79a9af862, 0x55ffcc55666699ff, 0x94a722941111b6a7, 0xcf4a0fcf8a8ac04a, 0x1030c910e9e9d930, 0x060a080604040e0a, 0x8198e781fefe6698, 0xf00b5bf0a0a0ab0b, 0x44ccf0447878b4cc, 0xbad54aba2525f0d5, 0xe33e96e34b4b753e, 0xf30e5ff3a2a2ac0e, 0xfe19bafe5d5d4419, 0xc05b1bc08080db5b, 0x8a850a8a05058085, 0xadec7ead3f3fd3ec, 0xbcdf42bc2121fedf, 0x48d8e0487070a8d8, 0x040cf904f1f1fd0c, 0xdf7ac6df6363197a, 0xc158eec177772f58, 0x759f4575afaf309f, 0x63a584634242e7a5, 0x3050403020207050, 0x1a2ed11ae5e5cb2e, 0x0e12e10efdfdef12, 0x6db7656dbfbf08b7, 0x4cd4194c818155d4, 0x143c30141818243c, 0x355f4c352626795f, 0x2f719d2fc3c3b271, 0xe13867e1bebe8638, 0xa2fd6aa23535c8fd, 0xcc4f0bcc8888c74f, 0x394b5c392e2e654b, 0x57f93d5793936af9, 0xf20daaf25555580d, 0x829de382fcfc619d, 0x47c9f4477a7ab3c9, 0xacef8bacc8c827ef, 0xe7326fe7baba8832, 0x2b7d642b32324f7d, 0x95a4d795e6e642a4, 0xa0fb9ba0c0c03bfb, 0x98b332981919aab3, 0xd16827d19e9ef668, 0x7f815d7fa3a32281, 0x66aa88664444eeaa, 0x7e82a87e5454d682, 0xabe676ab3b3bdde6, 0x839e16830b0b959e, 0xca4503ca8c8cc945, 0x297b9529c7c7bc7b, 0xd36ed6d36b6b056e, 0x3c44503c28286c44, 0x798b5579a7a72c8b, 0xe23d63e2bcbc813d, 0x1d272c1d16163127, 0x769a4176adad379a, 0x3b4dad3bdbdb964d, 0x56fac85664649efa, 0x4ed2e84e7474a6d2, 0x1e22281e14143622, 0xdb763fdb9292e476, 0x0a1e180a0c0c121e, 0x6cb4906c4848fcb4, 0xe4376be4b8b88f37, 0x5de7255d9f9f78e7, 0x6eb2616ebdbd0fb2, 0xef2a86ef4343692a, 0xa6f193a6c4c435f1, 0xa8e372a83939dae3, 0xa4f762a43131c6f7, 0x3759bd37d3d38a59, 0x8b86ff8bf2f27486, 0x3256b132d5d58356, 0x43c50d438b8b4ec5, 0x59ebdc596e6e85eb, 0xb7c2afb7dada18c2, 0x8c8f028c01018e8f, 0x64ac7964b1b11dac, 0xd26d23d29c9cf16d, 0xe03b92e04949723b, 0xb4c7abb4d8d81fc7, 0xfa1543faacacb915, 0x0709fd07f3f3fa09, 0x256f8525cfcfa06f, 0xafea8fafcaca20ea, 0x8e89f38ef4f47d89, 0xe9208ee947476720, 0x1828201810103828, 0xd564ded56f6f0b64, 0x8883fb88f0f07383, 0x6fb1946f4a4afbb1, 0x7296b8725c5cca96, 0x246c70243838546c, 0xf108aef157575f08, 0xc752e6c773732152, 0x51f33551979764f3, 0x23658d23cbcbae65, 0x7c84597ca1a12584, 0x9cbfcb9ce8e857bf, 0x21637c213e3e5d63, 0xdd7c37dd9696ea7c, 0xdc7fc2dc61611e7f, 0x86911a860d0d9c91, 0x85941e850f0f9b94, 0x90abdb90e0e04bab, 0x42c6f8427c7cbac6, 0xc457e2c471712657, 0xaae583aacccc29e5, 0xd8733bd89090e373, 0x050f0c050606090f, 0x0103f501f7f7f403, 0x123638121c1c2a36, 0xa3fe9fa3c2c23cfe, 0x5fe1d45f6a6a8be1, 0xf91047f9aeaebe10, 0xd06bd2d06969026b, 0x91a82e911717bfa8, 0x58e82958999971e8, 0x276974273a3a5369, 0xb9d04eb92727f7d0, 0x3848a938d9d99148, 0x1335cd13ebebde35, 0xb3ce56b32b2be5ce, 0x3355443322227755, 0xbbd6bfbbd2d204d6, 0x70904970a9a93990, 0x89800e8907078780, 0xa7f266a73333c1f2, 0xb6c15ab62d2decc1, 0x226678223c3c5a66, 0x92ad2a921515b8ad, 0x20608920c9c9a960, 0x49db154987875cdb, 0xff1a4fffaaaab01a, 0x7888a0785050d888, 0x7a8e517aa5a52b8e, 0x8f8a068f0303898a, 0xf813b2f859594a13, 0x809b12800909929b, 0x173934171a1a2339, 0xda75cada65651075, 0x3153b531d7d78453, 0xc65113c68484d551, 0xb8d3bbb8d0d003d3, 0xc35e1fc38282dc5e, 0xb0cb52b02929e2cb, 0x7799b4775a5ac399, 0x11333c111e1e2d33, 0xcb46f6cb7b7b3d46, 0xfc1f4bfca8a8b71f, 0xd661dad66d6d0c61, 0x3a4e583a2c2c624e], + [0xf4a5f497a5c6c632, 0x978497eb84f8f86f, 0xb099b0c799eeee5e, 0x8c8d8cf78df6f67a, 0x170d17e50dffffe8, 0xdcbddcb7bdd6d60a, 0xc8b1c8a7b1dede16, 0xfc54fc395491916d, 0xf050f0c050606090, 0x0503050403020207, 0xe0a9e087a9cece2e, 0x877d87ac7d5656d1, 0x2b192bd519e7e7cc, 0xa662a67162b5b513, 0x31e6319ae64d4d7c, 0xb59ab5c39aecec59, 0xcf45cf05458f8f40, 0xbc9dbc3e9d1f1fa3, 0xc040c00940898949, 0x928792ef87fafa68, 0x3f153fc515efefd0, 0x26eb267febb2b294, 0x40c94007c98e8ece, 0x1d0b1ded0bfbfbe6, 0x2fec2f82ec41416e, 0xa967a97d67b3b31a, 0x1cfd1cbefd5f5f43, 0x25ea258aea454560, 0xdabfda46bf2323f9, 0x02f702a6f7535351, 0xa196a1d396e4e445, 0xed5bed2d5b9b9b76, 0x5dc25deac2757528, 0x241c24d91ce1e1c5, 0xe9aee97aae3d3dd4, 0xbe6abe986a4c4cf2, 0xee5aeed85a6c6c82, 0xc341c3fc417e7ebd, 0x060206f102f5f5f3, 0xd14fd11d4f838352, 0xe45ce4d05c68688c, 0x07f407a2f4515156, 0x5c345cb934d1d18d, 0x180818e908f9f9e1, 0xae93aedf93e2e24c, 0x9573954d73abab3e, 0xf553f5c453626297, 0x413f41543f2a2a6b, 0x140c14100c08081c, 0xf652f63152959563, 0xaf65af8c654646e9, 0xe25ee2215e9d9d7f, 0x7828786028303048, 0xf8a1f86ea13737cf, 0x110f11140f0a0a1b, 0xc4b5c45eb52f2feb, 0x1b091b1c090e0e15, 0x5a365a483624247e, 0xb69bb6369b1b1bad, 0x473d47a53ddfdf98, 0x6a266a8126cdcda7, 0xbb69bb9c694e4ef5, 0x4ccd4cfecd7f7f33, 0xba9fbacf9feaea50, 0x2d1b2d241b12123f, 0xb99eb93a9e1d1da4, 0x9c749cb0745858c4, 0x722e72682e343446, 0x772d776c2d363641, 0xcdb2cda3b2dcdc11, 0x29ee2973eeb4b49d, 0x16fb16b6fb5b5b4d, 0x01f60153f6a4a4a5, 0xd74dd7ec4d7676a1, 0xa361a37561b7b714, 0x49ce49face7d7d34, 0x8d7b8da47b5252df, 0x423e42a13edddd9f, 0x937193bc715e5ecd, 0xa297a226971313b1, 0x04f50457f5a6a6a2, 0xb868b86968b9b901, 0x0000000000000000, 0x742c74992cc1c1b5, 0xa060a080604040e0, 0x211f21dd1fe3e3c2, 0x43c843f2c879793a, 0x2ced2c77edb6b69a, 0xd9bed9b3bed4d40d, 0xca46ca01468d8d47, 0x70d970ced9676717, 0xdd4bdde44b7272af, 0x79de7933de9494ed, 0x67d4672bd49898ff, 0x23e8237be8b0b093, 0xde4ade114a85855b, 0xbd6bbd6d6bbbbb06, 0x7e2a7e912ac5c5bb, 0x34e5349ee54f4f7b, 0x3a163ac116ededd7, 0x54c55417c58686d2, 0x62d7622fd79a9af8, 0xff55ffcc55666699, 0xa794a722941111b6, 0x4acf4a0fcf8a8ac0, 0x301030c910e9e9d9, 0x0a060a080604040e, 0x988198e781fefe66, 0x0bf00b5bf0a0a0ab, 0xcc44ccf0447878b4, 0xd5bad54aba2525f0, 0x3ee33e96e34b4b75, 0x0ef30e5ff3a2a2ac, 0x19fe19bafe5d5d44, 0x5bc05b1bc08080db, 0x858a850a8a050580, 0xecadec7ead3f3fd3, 0xdfbcdf42bc2121fe, 0xd848d8e0487070a8, 0x0c040cf904f1f1fd, 0x7adf7ac6df636319, 0x58c158eec177772f, 0x9f759f4575afaf30, 0xa563a584634242e7, 0x5030504030202070, 0x2e1a2ed11ae5e5cb, 0x120e12e10efdfdef, 0xb76db7656dbfbf08, 0xd44cd4194c818155, 0x3c143c3014181824, 0x5f355f4c35262679, 0x712f719d2fc3c3b2, 0x38e13867e1bebe86, 0xfda2fd6aa23535c8, 0x4fcc4f0bcc8888c7, 0x4b394b5c392e2e65, 0xf957f93d5793936a, 0x0df20daaf2555558, 0x9d829de382fcfc61, 0xc947c9f4477a7ab3, 0xefacef8bacc8c827, 0x32e7326fe7baba88, 0x7d2b7d642b32324f, 0xa495a4d795e6e642, 0xfba0fb9ba0c0c03b, 0xb398b332981919aa, 0x68d16827d19e9ef6, 0x817f815d7fa3a322, 0xaa66aa88664444ee, 0x827e82a87e5454d6, 0xe6abe676ab3b3bdd, 0x9e839e16830b0b95, 0x45ca4503ca8c8cc9, 0x7b297b9529c7c7bc, 0x6ed36ed6d36b6b05, 0x443c44503c28286c, 0x8b798b5579a7a72c, 0x3de23d63e2bcbc81, 0x271d272c1d161631, 0x9a769a4176adad37, 0x4d3b4dad3bdbdb96, 0xfa56fac85664649e, 0xd24ed2e84e7474a6, 0x221e22281e141436, 0x76db763fdb9292e4, 0x1e0a1e180a0c0c12, 0xb46cb4906c4848fc, 0x37e4376be4b8b88f, 0xe75de7255d9f9f78, 0xb26eb2616ebdbd0f, 0x2aef2a86ef434369, 0xf1a6f193a6c4c435, 0xe3a8e372a83939da, 0xf7a4f762a43131c6, 0x593759bd37d3d38a, 0x868b86ff8bf2f274, 0x563256b132d5d583, 0xc543c50d438b8b4e, 0xeb59ebdc596e6e85, 0xc2b7c2afb7dada18, 0x8f8c8f028c01018e, 0xac64ac7964b1b11d, 0x6dd26d23d29c9cf1, 0x3be03b92e0494972, 0xc7b4c7abb4d8d81f, 0x15fa1543faacacb9, 0x090709fd07f3f3fa, 0x6f256f8525cfcfa0, 0xeaafea8fafcaca20, 0x898e89f38ef4f47d, 0x20e9208ee9474767, 0x2818282018101038, 0x64d564ded56f6f0b, 0x838883fb88f0f073, 0xb16fb1946f4a4afb, 0x967296b8725c5cca, 0x6c246c7024383854, 0x08f108aef157575f, 0x52c752e6c7737321, 0xf351f33551979764, 0x6523658d23cbcbae, 0x847c84597ca1a125, 0xbf9cbfcb9ce8e857, 0x6321637c213e3e5d, 0x7cdd7c37dd9696ea, 0x7fdc7fc2dc61611e, 0x9186911a860d0d9c, 0x9485941e850f0f9b, 0xab90abdb90e0e04b, 0xc642c6f8427c7cba, 0x57c457e2c4717126, 0xe5aae583aacccc29, 0x73d8733bd89090e3, 0x0f050f0c05060609, 0x030103f501f7f7f4, 0x36123638121c1c2a, 0xfea3fe9fa3c2c23c, 0xe15fe1d45f6a6a8b, 0x10f91047f9aeaebe, 0x6bd06bd2d0696902, 0xa891a82e911717bf, 0xe858e82958999971, 0x69276974273a3a53, 0xd0b9d04eb92727f7, 0x483848a938d9d991, 0x351335cd13ebebde, 0xceb3ce56b32b2be5, 0x5533554433222277, 0xd6bbd6bfbbd2d204, 0x9070904970a9a939, 0x8089800e89070787, 0xf2a7f266a73333c1, 0xc1b6c15ab62d2dec, 0x66226678223c3c5a, 0xad92ad2a921515b8, 0x6020608920c9c9a9, 0xdb49db154987875c, 0x1aff1a4fffaaaab0, 0x887888a0785050d8, 0x8e7a8e517aa5a52b, 0x8a8f8a068f030389, 0x13f813b2f859594a, 0x9b809b1280090992, 0x39173934171a1a23, 0x75da75cada656510, 0x533153b531d7d784, 0x51c65113c68484d5, 0xd3b8d3bbb8d0d003, 0x5ec35e1fc38282dc, 0xcbb0cb52b02929e2, 0x997799b4775a5ac3, 0x3311333c111e1e2d, 0x46cb46f6cb7b7b3d, 0x1ffc1f4bfca8a8b7, 0x61d661dad66d6d0c, 0x4e3a4e583a2c2c62], + [0x32f4a5f497a5c6c6, 0x6f978497eb84f8f8, 0x5eb099b0c799eeee, 0x7a8c8d8cf78df6f6, 0xe8170d17e50dffff, 0x0adcbddcb7bdd6d6, 0x16c8b1c8a7b1dede, 0x6dfc54fc39549191, 0x90f050f0c0506060, 0x0705030504030202, 0x2ee0a9e087a9cece, 0xd1877d87ac7d5656, 0xcc2b192bd519e7e7, 0x13a662a67162b5b5, 0x7c31e6319ae64d4d, 0x59b59ab5c39aecec, 0x40cf45cf05458f8f, 0xa3bc9dbc3e9d1f1f, 0x49c040c009408989, 0x68928792ef87fafa, 0xd03f153fc515efef, 0x9426eb267febb2b2, 0xce40c94007c98e8e, 0xe61d0b1ded0bfbfb, 0x6e2fec2f82ec4141, 0x1aa967a97d67b3b3, 0x431cfd1cbefd5f5f, 0x6025ea258aea4545, 0xf9dabfda46bf2323, 0x5102f702a6f75353, 0x45a196a1d396e4e4, 0x76ed5bed2d5b9b9b, 0x285dc25deac27575, 0xc5241c24d91ce1e1, 0xd4e9aee97aae3d3d, 0xf2be6abe986a4c4c, 0x82ee5aeed85a6c6c, 0xbdc341c3fc417e7e, 0xf3060206f102f5f5, 0x52d14fd11d4f8383, 0x8ce45ce4d05c6868, 0x5607f407a2f45151, 0x8d5c345cb934d1d1, 0xe1180818e908f9f9, 0x4cae93aedf93e2e2, 0x3e9573954d73abab, 0x97f553f5c4536262, 0x6b413f41543f2a2a, 0x1c140c14100c0808, 0x63f652f631529595, 0xe9af65af8c654646, 0x7fe25ee2215e9d9d, 0x4878287860283030, 0xcff8a1f86ea13737, 0x1b110f11140f0a0a, 0xebc4b5c45eb52f2f, 0x151b091b1c090e0e, 0x7e5a365a48362424, 0xadb69bb6369b1b1b, 0x98473d47a53ddfdf, 0xa76a266a8126cdcd, 0xf5bb69bb9c694e4e, 0x334ccd4cfecd7f7f, 0x50ba9fbacf9feaea, 0x3f2d1b2d241b1212, 0xa4b99eb93a9e1d1d, 0xc49c749cb0745858, 0x46722e72682e3434, 0x41772d776c2d3636, 0x11cdb2cda3b2dcdc, 0x9d29ee2973eeb4b4, 0x4d16fb16b6fb5b5b, 0xa501f60153f6a4a4, 0xa1d74dd7ec4d7676, 0x14a361a37561b7b7, 0x3449ce49face7d7d, 0xdf8d7b8da47b5252, 0x9f423e42a13edddd, 0xcd937193bc715e5e, 0xb1a297a226971313, 0xa204f50457f5a6a6, 0x01b868b86968b9b9, 0x0000000000000000, 0xb5742c74992cc1c1, 0xe0a060a080604040, 0xc2211f21dd1fe3e3, 0x3a43c843f2c87979, 0x9a2ced2c77edb6b6, 0x0dd9bed9b3bed4d4, 0x47ca46ca01468d8d, 0x1770d970ced96767, 0xafdd4bdde44b7272, 0xed79de7933de9494, 0xff67d4672bd49898, 0x9323e8237be8b0b0, 0x5bde4ade114a8585, 0x06bd6bbd6d6bbbbb, 0xbb7e2a7e912ac5c5, 0x7b34e5349ee54f4f, 0xd73a163ac116eded, 0xd254c55417c58686, 0xf862d7622fd79a9a, 0x99ff55ffcc556666, 0xb6a794a722941111, 0xc04acf4a0fcf8a8a, 0xd9301030c910e9e9, 0x0e0a060a08060404, 0x66988198e781fefe, 0xab0bf00b5bf0a0a0, 0xb4cc44ccf0447878, 0xf0d5bad54aba2525, 0x753ee33e96e34b4b, 0xac0ef30e5ff3a2a2, 0x4419fe19bafe5d5d, 0xdb5bc05b1bc08080, 0x80858a850a8a0505, 0xd3ecadec7ead3f3f, 0xfedfbcdf42bc2121, 0xa8d848d8e0487070, 0xfd0c040cf904f1f1, 0x197adf7ac6df6363, 0x2f58c158eec17777, 0x309f759f4575afaf, 0xe7a563a584634242, 0x7050305040302020, 0xcb2e1a2ed11ae5e5, 0xef120e12e10efdfd, 0x08b76db7656dbfbf, 0x55d44cd4194c8181, 0x243c143c30141818, 0x795f355f4c352626, 0xb2712f719d2fc3c3, 0x8638e13867e1bebe, 0xc8fda2fd6aa23535, 0xc74fcc4f0bcc8888, 0x654b394b5c392e2e, 0x6af957f93d579393, 0x580df20daaf25555, 0x619d829de382fcfc, 0xb3c947c9f4477a7a, 0x27efacef8bacc8c8, 0x8832e7326fe7baba, 0x4f7d2b7d642b3232, 0x42a495a4d795e6e6, 0x3bfba0fb9ba0c0c0, 0xaab398b332981919, 0xf668d16827d19e9e, 0x22817f815d7fa3a3, 0xeeaa66aa88664444, 0xd6827e82a87e5454, 0xdde6abe676ab3b3b, 0x959e839e16830b0b, 0xc945ca4503ca8c8c, 0xbc7b297b9529c7c7, 0x056ed36ed6d36b6b, 0x6c443c44503c2828, 0x2c8b798b5579a7a7, 0x813de23d63e2bcbc, 0x31271d272c1d1616, 0x379a769a4176adad, 0x964d3b4dad3bdbdb, 0x9efa56fac8566464, 0xa6d24ed2e84e7474, 0x36221e22281e1414, 0xe476db763fdb9292, 0x121e0a1e180a0c0c, 0xfcb46cb4906c4848, 0x8f37e4376be4b8b8, 0x78e75de7255d9f9f, 0x0fb26eb2616ebdbd, 0x692aef2a86ef4343, 0x35f1a6f193a6c4c4, 0xdae3a8e372a83939, 0xc6f7a4f762a43131, 0x8a593759bd37d3d3, 0x74868b86ff8bf2f2, 0x83563256b132d5d5, 0x4ec543c50d438b8b, 0x85eb59ebdc596e6e, 0x18c2b7c2afb7dada, 0x8e8f8c8f028c0101, 0x1dac64ac7964b1b1, 0xf16dd26d23d29c9c, 0x723be03b92e04949, 0x1fc7b4c7abb4d8d8, 0xb915fa1543faacac, 0xfa090709fd07f3f3, 0xa06f256f8525cfcf, 0x20eaafea8fafcaca, 0x7d898e89f38ef4f4, 0x6720e9208ee94747, 0x3828182820181010, 0x0b64d564ded56f6f, 0x73838883fb88f0f0, 0xfbb16fb1946f4a4a, 0xca967296b8725c5c, 0x546c246c70243838, 0x5f08f108aef15757, 0x2152c752e6c77373, 0x64f351f335519797, 0xae6523658d23cbcb, 0x25847c84597ca1a1, 0x57bf9cbfcb9ce8e8, 0x5d6321637c213e3e, 0xea7cdd7c37dd9696, 0x1e7fdc7fc2dc6161, 0x9c9186911a860d0d, 0x9b9485941e850f0f, 0x4bab90abdb90e0e0, 0xbac642c6f8427c7c, 0x2657c457e2c47171, 0x29e5aae583aacccc, 0xe373d8733bd89090, 0x090f050f0c050606, 0xf4030103f501f7f7, 0x2a36123638121c1c, 0x3cfea3fe9fa3c2c2, 0x8be15fe1d45f6a6a, 0xbe10f91047f9aeae, 0x026bd06bd2d06969, 0xbfa891a82e911717, 0x71e858e829589999, 0x5369276974273a3a, 0xf7d0b9d04eb92727, 0x91483848a938d9d9, 0xde351335cd13ebeb, 0xe5ceb3ce56b32b2b, 0x7755335544332222, 0x04d6bbd6bfbbd2d2, 0x399070904970a9a9, 0x878089800e890707, 0xc1f2a7f266a73333, 0xecc1b6c15ab62d2d, 0x5a66226678223c3c, 0xb8ad92ad2a921515, 0xa96020608920c9c9, 0x5cdb49db15498787, 0xb01aff1a4fffaaaa, 0xd8887888a0785050, 0x2b8e7a8e517aa5a5, 0x898a8f8a068f0303, 0x4a13f813b2f85959, 0x929b809b12800909, 0x2339173934171a1a, 0x1075da75cada6565, 0x84533153b531d7d7, 0xd551c65113c68484, 0x03d3b8d3bbb8d0d0, 0xdc5ec35e1fc38282, 0xe2cbb0cb52b02929, 0xc3997799b4775a5a, 0x2d3311333c111e1e, 0x3d46cb46f6cb7b7b, 0xb71ffc1f4bfca8a8, 0x0c61d661dad66d6d, 0x624e3a4e583a2c2c], +]; diff --git a/groestl/tests/data/groestl224.blb b/groestl/tests/data/groestl224.blb index 090b5473e..1705d414c 100644 Binary files a/groestl/tests/data/groestl224.blb and b/groestl/tests/data/groestl224.blb differ diff --git a/groestl/tests/data/groestl256.blb b/groestl/tests/data/groestl256.blb index b24aed4db..122de3971 100644 Binary files a/groestl/tests/data/groestl256.blb and b/groestl/tests/data/groestl256.blb differ diff --git a/groestl/tests/data/groestl384.blb b/groestl/tests/data/groestl384.blb index 72174f6a8..cf0e6a152 100644 Binary files a/groestl/tests/data/groestl384.blb and b/groestl/tests/data/groestl384.blb differ diff --git a/groestl/tests/data/groestl512.blb b/groestl/tests/data/groestl512.blb index 89b904f19..24ce9ee34 100644 Binary files a/groestl/tests/data/groestl512.blb and b/groestl/tests/data/groestl512.blb differ diff --git a/k12/CHANGELOG.md b/k12/CHANGELOG.md index da46bb91a..c6400fda1 100644 --- a/k12/CHANGELOG.md +++ b/k12/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## 0.2.0 (2021-11-22) +### Changed +- Update to `digest` v0.10 ([#217]) + +[#217]: https://github.com/RustCrypto/hashes/pull/217 + ## 0.1.0 (2020-06-09) ### Changed - Update to `digest` v0.9 release; MSRV 1.41+ ([#155]) diff --git a/k12/Cargo.toml b/k12/Cargo.toml index 7b227d4dd..d736e0827 100644 --- a/k12/Cargo.toml +++ b/k12/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "k12" -version = "0.1.0" +version = "0.2.0" # Also update html_root_url in lib.rs when bumping this description = "Experimental pure Rust implementation of the KangarooTwelve hash function" authors = ["Diggory Hardy "] license = "Apache-2.0 OR MIT" @@ -12,10 +12,10 @@ keywords = ["crypto", "hash", "digest"] categories = ["cryptography", "no-std"] [dependencies] -digest = { version = "0.9", features = ["alloc"] } +digest = { version = "0.10", features = ["alloc"] } [dev-dependencies] -digest = { version = "0.9", features = ["alloc", "dev"] } +digest = { version = "0.10", features = ["alloc", "dev"] } hex-literal = "0.2" [features] diff --git a/k12/src/lib.rs b/k12/src/lib.rs index 8c467d869..47e15deb3 100644 --- a/k12/src/lib.rs +++ b/k12/src/lib.rs @@ -10,8 +10,9 @@ #![no_std] #![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_root_url = "https://docs.rs/k12/0.2.0" )] #![forbid(unsafe_code)] #![warn(missing_docs, rust_2018_idioms)] @@ -28,7 +29,7 @@ mod lanes; // TODO(tarcieri): eliminate usage of `Vec` use alloc::vec::Vec; use core::{cmp::min, convert::TryInto, mem}; -use digest::{ExtendableOutputDirty, Reset, Update, XofReader}; +use digest::{ExtendableOutput, HashMarker, Reset, Update, XofReader}; /// The KangarooTwelve extendable-output function (XOF). #[derive(Debug, Default)] @@ -57,17 +58,26 @@ impl KangarooTwelve { } } +impl HashMarker for KangarooTwelve {} + impl Update for KangarooTwelve { - /// Input data into the hash function - fn update(&mut self, bytes: impl AsRef<[u8]>) { - self.buffer.extend_from_slice(bytes.as_ref()); + fn update(&mut self, bytes: &[u8]) { + self.buffer.extend_from_slice(bytes); } } -impl ExtendableOutputDirty for KangarooTwelve { +impl ExtendableOutput for KangarooTwelve { type Reader = Reader; - fn finalize_xof_dirty(&mut self) -> Self::Reader { + fn finalize_xof(self) -> Self::Reader { + Reader { + buffer: self.buffer, + customization: self.customization, + finished: false, + } + } + + fn finalize_xof_reset(&mut self) -> Self::Reader { let mut buffer = vec![]; let mut customization = vec![]; diff --git a/k12/tests/lib.rs b/k12/tests/lib.rs index a71c0a2cd..e6ddc4434 100644 --- a/k12/tests/lib.rs +++ b/k12/tests/lib.rs @@ -4,6 +4,12 @@ use k12::{ KangarooTwelve, }; +fn digest_and_box(data: &[u8], n: usize) -> Box<[u8]> { + let mut h = KangarooTwelve::new(); + h.update(data); + h.finalize_boxed(n) +} + fn read_bytes>(s: T) -> Box<[u8]> { fn b(c: u8) -> u8 { match c { @@ -36,7 +42,7 @@ fn read_bytes>(s: T) -> Box<[u8]> { fn empty() { // Source: reference paper assert_eq!( - KangarooTwelve::new().chain(b"").finalize_boxed(32), + digest_and_box(b"", 32), read_bytes( "1a c2 d4 50 fc 3b 42 05 d1 9d a7 bf ca 1b 37 51 3c 08 03 57 7a c7 16 7f 06 fe 2c e1 f0 ef 39 e5" @@ -44,7 +50,7 @@ fn empty() { ); assert_eq!( - KangarooTwelve::new().chain(b"").finalize_boxed(64), + digest_and_box(b"", 64), read_bytes( "1a c2 d4 50 fc 3b 42 05 d1 9d a7 bf ca 1b 37 51 3c 08 03 57 7a c7 16 7f 06 fe 2c e1 f0 ef 39 e5 42 69 c0 56 b8 c8 2e @@ -53,7 +59,7 @@ fn empty() { ); assert_eq!( - KangarooTwelve::new().chain(b"").finalize_boxed(10032)[10000..], + digest_and_box(b"", 10032)[10000..], read_bytes( "e8 dc 56 36 42 f7 22 8c 84 68 4c 89 84 05 d3 a8 34 79 91 58 c0 79 b1 28 80 27 7a 1d 28 e2 ff 6d" @@ -84,7 +90,7 @@ fn pat_m() { { let len = 17usize.pow(i); let m: Vec = (0..len).map(|j| (j % 251) as u8).collect(); - let result = KangarooTwelve::new().chain(&m).finalize_boxed(32); + let result = digest_and_box(&m, 32); assert_eq!(result, read_bytes(expected[i as usize])); } } @@ -105,9 +111,9 @@ fn pat_c() { let m: Vec = iter::repeat(0xFF).take(2usize.pow(i) - 1).collect(); let len = 41usize.pow(i); let c: Vec = (0..len).map(|j| (j % 251) as u8).collect(); - let result = KangarooTwelve::new_with_customization(c) - .chain(&m) - .finalize_boxed(32); + let mut h = KangarooTwelve::new_with_customization(c); + h.update(&m); + let result = h.finalize_boxed(32); assert_eq!(result, read_bytes(expected[i as usize])); } } diff --git a/md2/CHANGELOG.md b/md2/CHANGELOG.md index 2319dae63..aaec8e9e1 100644 --- a/md2/CHANGELOG.md +++ b/md2/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## 0.10.0 (2021-11-22) +### Changed +- Update to `digest` v0.10 ([#217]) + +[#217]: https://github.com/RustCrypto/hashes/pull/217 + ## 0.9.0 (2020-06-12) ### Changed - Bump `opaque-debug` to v0.3.0 ([#168]) diff --git a/md2/Cargo.toml b/md2/Cargo.toml index a025061d8..33b7833fc 100644 --- a/md2/Cargo.toml +++ b/md2/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "md2" -version = "0.9.0" +version = "0.10.0" # Also update html_root_url in lib.rs when bumping this license = "MIT OR Apache-2.0" authors = ["RustCrypto Developers"] description = "MD2 hash function" @@ -12,12 +12,10 @@ keywords = ["crypto", "md2", "hash", "digest"] categories = ["cryptography", "no-std"] [dependencies] -digest = "0.9" -block-buffer = { version = "0.9", features = ["block-padding"] } -opaque-debug = "0.3" +digest = "0.10" [dev-dependencies] -digest = { version = "0.9", features = ["dev"] } +digest = { version = "0.10", features = ["dev"] } hex-literal = "0.2" [features] diff --git a/md2/examples/md2sum.rs b/md2/examples/md2sum.rs deleted file mode 100644 index 14a94ff78..000000000 --- a/md2/examples/md2sum.rs +++ /dev/null @@ -1,39 +0,0 @@ -use md2::{Digest, Md2}; -use std::env; -use std::fs; -use std::io::{self, Read}; - -const BUFFER_SIZE: usize = 1024; - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = Md2::new(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - println!("{:x}\t{}", &sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process(&mut file, &path); - } - } - } else { - process(&mut io::stdin(), "-"); - } -} diff --git a/md2/src/lib.rs b/md2/src/lib.rs index 07ca1e68c..d41a1178e 100644 --- a/md2/src/lib.rs +++ b/md2/src/lib.rs @@ -25,52 +25,40 @@ #![no_std] #![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_root_url = "https://docs.rs/md2/0.10.0" )] #![deny(unsafe_code)] #![warn(missing_docs, rust_2018_idioms)] -#[cfg(feature = "std")] -extern crate std; - pub use digest::{self, Digest}; -use block_buffer::{block_padding::Pkcs7, BlockBuffer}; -use digest::{consts::U16, generic_array::GenericArray}; -use digest::{BlockInput, FixedOutputDirty, Reset, Update}; +use core::fmt; +use digest::{ + block_buffer::Eager, + consts::U16, + core_api::{ + AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore, + OutputSizeUser, Reset, UpdateCore, + }, + HashMarker, Output, +}; mod consts; -type Block = GenericArray; - +/// Core MD2 hasher state. #[derive(Clone)] -struct Md2State { +pub struct Md2Core { x: [u8; 48], - checksum: Block, -} - -impl Default for Md2State { - fn default() -> Self { - Self { - x: [0; 48], - checksum: Default::default(), - } - } -} - -/// The MD2 hasher -#[derive(Clone, Default)] -pub struct Md2 { - buffer: BlockBuffer, - state: Md2State, + checksum: Block, } -impl Md2State { - fn process_block(&mut self, input: &Block) { +impl Md2Core { + fn compress(&mut self, block: &Block) { // Update state for j in 0..16 { - self.x[16 + j] = input[j]; + self.x[16 + j] = block[j]; self.x[32 + j] = self.x[16 + j] ^ self.x[j]; } @@ -86,48 +74,78 @@ impl Md2State { // Update checksum let mut l = self.checksum[15]; for j in 0..16 { - self.checksum[j] ^= consts::S[(input[j] ^ l) as usize]; + self.checksum[j] ^= consts::S[(block[j] ^ l) as usize]; l = self.checksum[j]; } } } -impl BlockInput for Md2 { +impl HashMarker for Md2Core {} + +impl BlockSizeUser for Md2Core { type BlockSize = U16; } -impl Update for Md2 { - fn update(&mut self, input: impl AsRef<[u8]>) { - let input = input.as_ref(); - let s = &mut self.state; - self.buffer.input_block(input, |d| s.process_block(d)); - } +impl BufferKindUser for Md2Core { + type BufferKind = Eager; } -impl FixedOutputDirty for Md2 { +impl OutputSizeUser for Md2Core { type OutputSize = U16; +} - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - let buf = self - .buffer - .pad_with::() - .expect("we never use input_lazy"); - - self.state.process_block(buf); +impl UpdateCore for Md2Core { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + for block in blocks { + self.compress(block) + } + } +} - let checksum = self.state.checksum; - self.state.process_block(&checksum); +impl FixedOutputCore for Md2Core { + #[inline] + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + let pos = buffer.get_pos(); + let rem = buffer.remaining() as u8; + let block = buffer.pad_with_zeros(); + block[pos..].iter_mut().for_each(|b| *b = rem); + + self.compress(block); + let checksum = self.checksum; + self.compress(&checksum); + out.copy_from_slice(&self.x[0..16]); + } +} - out.copy_from_slice(&self.state.x[0..16]); +impl Default for Md2Core { + #[inline] + fn default() -> Self { + Self { + x: [0; 48], + checksum: Default::default(), + } } } -impl Reset for Md2 { +impl Reset for Md2Core { + #[inline] fn reset(&mut self) { - self.state = Default::default(); - self.buffer.reset(); + *self = Default::default(); + } +} + +impl AlgorithmName for Md2Core { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Md2") + } +} + +impl fmt::Debug for Md2Core { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Md2Core { ... }") } } -opaque_debug::implement!(Md2); -digest::impl_write!(Md2); +/// MD2 hasher state. +pub type Md2 = CoreWrapper; diff --git a/md2/tests/data/md2.blb b/md2/tests/data/md2.blb index 4b03cb78d..986c38e60 100644 Binary files a/md2/tests/data/md2.blb and b/md2/tests/data/md2.blb differ diff --git a/md4/CHANGELOG.md b/md4/CHANGELOG.md index b4728c816..fae44bebc 100644 --- a/md4/CHANGELOG.md +++ b/md4/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## 0.10.0 (2021-11-22) +### Changed +- Update to `digest` v0.10 ([#217]) + +[#217]: https://github.com/RustCrypto/hashes/pull/217 + ## 0.9.0 (2020-06-12) ### Changed - Bump `opaque-debug` to v0.3.0 ([#168]) diff --git a/md4/Cargo.toml b/md4/Cargo.toml index c2a53b5c0..23c0b6ace 100644 --- a/md4/Cargo.toml +++ b/md4/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "md4" -version = "0.9.0" +version = "0.10.0" # Also update html_root_url in lib.rs when bumping this description = "MD4 hash function" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -12,12 +12,10 @@ keywords = ["crypto", "md4", "hash", "digest"] categories = ["cryptography", "no-std"] [dependencies] -digest = "0.9" -block-buffer = "0.9" -opaque-debug = "0.3" +digest = "0.10" [dev-dependencies] -digest = { version = "0.9", features = ["dev"] } +digest = { version = "0.10", features = ["dev"] } hex-literal = "0.2" [features] diff --git a/md4/examples/md4sum.rs b/md4/examples/md4sum.rs deleted file mode 100644 index 4f4e67073..000000000 --- a/md4/examples/md4sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use md4::{Digest, Md4}; -use std::env; -use std::fs; -use std::io::{self, Read}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh: D = Default::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/md4/src/lib.rs b/md4/src/lib.rs index f2360fbf8..afbf0c31a 100644 --- a/md4/src/lib.rs +++ b/md4/src/lib.rs @@ -25,166 +25,175 @@ #![no_std] #![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_root_url = "https://docs.rs/md4/0.10.0" )] #![deny(unsafe_code)] #![warn(rust_2018_idioms)] #![allow(clippy::many_single_char_names)] -#[cfg(feature = "std")] -extern crate std; - -use core::convert::TryInto; pub use digest::{self, Digest}; -use block_buffer::BlockBuffer; +use core::{convert::TryInto, fmt}; use digest::{ - consts::{U16, U64}, - generic_array::GenericArray, + block_buffer::Eager, + core_api::{ + AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore, + OutputSizeUser, Reset, UpdateCore, + }, + generic_array::typenum::{Unsigned, U16, U64}, + HashMarker, Output, }; -use digest::{BlockInput, FixedOutputDirty, Reset, Update}; -// initial values for Md4State -const S: [u32; 4] = [0x6745_2301, 0xEFCD_AB89, 0x98BA_DCFE, 0x1032_5476]; +#[derive(Clone)] +pub struct Md4Core { + block_len: u64, + state: [u32; 4], +} -type Block = GenericArray; +impl HashMarker for Md4Core {} -#[derive(Copy, Clone)] -struct Md4State { - s: [u32; 4], +impl BlockSizeUser for Md4Core { + type BlockSize = U64; } -/// The MD4 hasher -#[derive(Clone, Default)] -pub struct Md4 { - length_bytes: u64, - buffer: BlockBuffer, - state: Md4State, +impl BufferKindUser for Md4Core { + type BufferKind = Eager; } -impl Md4State { - fn process_block(&mut self, input: &Block) { - fn f(x: u32, y: u32, z: u32) -> u32 { - (x & y) | (!x & z) - } +impl OutputSizeUser for Md4Core { + type OutputSize = U16; +} - fn g(x: u32, y: u32, z: u32) -> u32 { - (x & y) | (x & z) | (y & z) +impl UpdateCore for Md4Core { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + self.block_len = self.block_len.wrapping_add(blocks.len() as u64); + for block in blocks { + compress(&mut self.state, block); } + } +} - fn h(x: u32, y: u32, z: u32) -> u32 { - x ^ y ^ z +impl FixedOutputCore for Md4Core { + #[inline] + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + let bit_len = self + .block_len + .wrapping_mul(Self::BlockSize::U64) + .wrapping_add(buffer.get_pos() as u64) + .wrapping_mul(8); + let mut state = self.state; + buffer.len64_padding_le(bit_len, |block| compress(&mut state, block)); + + for (chunk, v) in out.chunks_exact_mut(4).zip(state.iter()) { + chunk.copy_from_slice(&v.to_le_bytes()); } + } +} - fn op1(a: u32, b: u32, c: u32, d: u32, k: u32, s: u32) -> u32 { - a.wrapping_add(f(b, c, d)).wrapping_add(k).rotate_left(s) +impl Default for Md4Core { + #[inline] + fn default() -> Self { + let state = [0x6745_2301, 0xEFCD_AB89, 0x98BA_DCFE, 0x1032_5476]; + Self { + state, + block_len: 0, } + } +} - fn op2(a: u32, b: u32, c: u32, d: u32, k: u32, s: u32) -> u32 { - a.wrapping_add(g(b, c, d)) - .wrapping_add(k) - .wrapping_add(0x5A82_7999) - .rotate_left(s) - } +impl Reset for Md4Core { + #[inline] + fn reset(&mut self) { + *self = Default::default(); + } +} - fn op3(a: u32, b: u32, c: u32, d: u32, k: u32, s: u32) -> u32 { - a.wrapping_add(h(b, c, d)) - .wrapping_add(k) - .wrapping_add(0x6ED9_EBA1) - .rotate_left(s) - } +impl AlgorithmName for Md4Core { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Md4") + } +} - let mut a = self.s[0]; - let mut b = self.s[1]; - let mut c = self.s[2]; - let mut d = self.s[3]; +impl fmt::Debug for Md4Core { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Md4Core { ... }") + } +} - // load block to data - let mut data = [0u32; 16]; - for (o, chunk) in data.iter_mut().zip(input.chunks_exact(4)) { - *o = u32::from_le_bytes(chunk.try_into().unwrap()); - } +/// MD4 hasher state. +pub type Md4 = CoreWrapper; - // round 1 - for &i in &[0, 4, 8, 12] { - a = op1(a, b, c, d, data[i], 3); - d = op1(d, a, b, c, data[i + 1], 7); - c = op1(c, d, a, b, data[i + 2], 11); - b = op1(b, c, d, a, data[i + 3], 19); - } +fn compress(state: &mut [u32; 4], input: &Block) { + fn f(x: u32, y: u32, z: u32) -> u32 { + (x & y) | (!x & z) + } - // round 2 - for i in 0..4 { - a = op2(a, b, c, d, data[i], 3); - d = op2(d, a, b, c, data[i + 4], 5); - c = op2(c, d, a, b, data[i + 8], 9); - b = op2(b, c, d, a, data[i + 12], 13); - } + fn g(x: u32, y: u32, z: u32) -> u32 { + (x & y) | (x & z) | (y & z) + } - // round 3 - for &i in &[0, 2, 1, 3] { - a = op3(a, b, c, d, data[i], 3); - d = op3(d, a, b, c, data[i + 8], 9); - c = op3(c, d, a, b, data[i + 4], 11); - b = op3(b, c, d, a, data[i + 12], 15); - } + fn h(x: u32, y: u32, z: u32) -> u32 { + x ^ y ^ z + } - self.s[0] = self.s[0].wrapping_add(a); - self.s[1] = self.s[1].wrapping_add(b); - self.s[2] = self.s[2].wrapping_add(c); - self.s[3] = self.s[3].wrapping_add(d); + fn op1(a: u32, b: u32, c: u32, d: u32, k: u32, s: u32) -> u32 { + a.wrapping_add(f(b, c, d)).wrapping_add(k).rotate_left(s) } -} -impl Default for Md4State { - fn default() -> Self { - Md4State { s: S } + fn op2(a: u32, b: u32, c: u32, d: u32, k: u32, s: u32) -> u32 { + a.wrapping_add(g(b, c, d)) + .wrapping_add(k) + .wrapping_add(0x5A82_7999) + .rotate_left(s) } -} -impl Md4 { - fn finalize_inner(&mut self) { - let state = &mut self.state; - let l = (self.length_bytes << 3) as u64; - self.buffer.len64_padding_le(l, |d| state.process_block(d)) + fn op3(a: u32, b: u32, c: u32, d: u32, k: u32, s: u32) -> u32 { + a.wrapping_add(h(b, c, d)) + .wrapping_add(k) + .wrapping_add(0x6ED9_EBA1) + .rotate_left(s) } -} -impl BlockInput for Md4 { - type BlockSize = U64; -} + let mut a = state[0]; + let mut b = state[1]; + let mut c = state[2]; + let mut d = state[3]; -impl Update for Md4 { - fn update(&mut self, input: impl AsRef<[u8]>) { - let input = input.as_ref(); - // Unlike Sha1 and Sha2, the length value in MD4 is defined as - // the length of the message mod 2^64 - ie: integer overflow is OK. - self.length_bytes = self.length_bytes.wrapping_add(input.len() as u64); - let s = &mut self.state; - self.buffer.input_block(input, |d| s.process_block(d)); + // load block to data + let mut data = [0u32; 16]; + for (o, chunk) in data.iter_mut().zip(input.chunks_exact(4)) { + *o = u32::from_le_bytes(chunk.try_into().unwrap()); } -} - -impl FixedOutputDirty for Md4 { - type OutputSize = U16; - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - self.finalize_inner(); + // round 1 + for &i in &[0, 4, 8, 12] { + a = op1(a, b, c, d, data[i], 3); + d = op1(d, a, b, c, data[i + 1], 7); + c = op1(c, d, a, b, data[i + 2], 11); + b = op1(b, c, d, a, data[i + 3], 19); + } - for (chunk, v) in out.chunks_exact_mut(4).zip(self.state.s.iter()) { - chunk.copy_from_slice(&v.to_le_bytes()); - } + // round 2 + for i in 0..4 { + a = op2(a, b, c, d, data[i], 3); + d = op2(d, a, b, c, data[i + 4], 5); + c = op2(c, d, a, b, data[i + 8], 9); + b = op2(b, c, d, a, data[i + 12], 13); } -} -impl Reset for Md4 { - fn reset(&mut self) { - self.state = Default::default(); - self.length_bytes = 0; - self.buffer.reset(); + // round 3 + for &i in &[0, 2, 1, 3] { + a = op3(a, b, c, d, data[i], 3); + d = op3(d, a, b, c, data[i + 8], 9); + c = op3(c, d, a, b, data[i + 4], 11); + b = op3(b, c, d, a, data[i + 12], 15); } -} -opaque_debug::implement!(Md4); -digest::impl_write!(Md4); + state[0] = state[0].wrapping_add(a); + state[1] = state[1].wrapping_add(b); + state[2] = state[2].wrapping_add(c); + state[3] = state[3].wrapping_add(d); +} diff --git a/md4/tests/data/md4.blb b/md4/tests/data/md4.blb index e590934ec..63ad206a5 100644 Binary files a/md4/tests/data/md4.blb and b/md4/tests/data/md4.blb differ diff --git a/md5/CHANGELOG.md b/md5/CHANGELOG.md index 5b573e207..677000da6 100644 --- a/md5/CHANGELOG.md +++ b/md5/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## 0.10.0 (2021-11-22) +### Changed +- Update to `digest` v0.10 ([#217]) + +[#217]: https://github.com/RustCrypto/hashes/pull/217 + ## 0.9.1 (2020-06-28) ### Changed - Update to `block-buffer` v0.9 ([#164]) diff --git a/md5/Cargo.toml b/md5/Cargo.toml index bf3292926..1c578e8f8 100644 --- a/md5/Cargo.toml +++ b/md5/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "md-5" -version = "0.9.1" +version = "0.10.0" # Also update html_root_url in lib.rs when bumping this description = "MD5 hash function" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -15,13 +15,11 @@ categories = ["cryptography", "no-std"] name = "md5" [dependencies] -digest = "0.9" -block-buffer = "0.9" -md5-asm = { version = "0.4", optional = true} -opaque-debug = "0.3" +digest = "0.10" +md5-asm = { version = "0.5", optional = true } [dev-dependencies] -digest = { version = "0.9", features = ["dev"] } +digest = { version = "0.10", features = ["dev"] } hex-literal = "0.2" [features] diff --git a/md5/examples/md5sum.rs b/md5/examples/md5sum.rs deleted file mode 100644 index baa91fcd3..000000000 --- a/md5/examples/md5sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use md5::{Digest, Md5}; -use std::env; -use std::fs; -use std::io::{self, Read}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = D::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/md5/src/utils.rs b/md5/src/compress.rs similarity index 79% rename from md5/src/utils.rs rename to md5/src/compress.rs index 9cd0259bc..46857038e 100644 --- a/md5/src/utils.rs +++ b/md5/src/compress.rs @@ -1,7 +1,21 @@ -#![allow(clippy::many_single_char_names)] -use crate::consts::RC; +#![allow(clippy::many_single_char_names, clippy::unreadable_literal)] use core::convert::TryInto; +const RC: [u32; 64] = [ + // round 1 + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + // round 2 + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + // round 3 + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + // round 4 + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, +]; + #[inline(always)] fn op_f(w: u32, x: u32, y: u32, z: u32, m: u32, c: u32, s: u32) -> u32 { ((x & y) | (!x & z)) @@ -42,7 +56,7 @@ fn op_i(w: u32, x: u32, y: u32, z: u32, m: u32, c: u32, s: u32) -> u32 { } #[inline] -pub fn compress(state: &mut [u32; 4], input: &[u8; 64]) { +pub fn compress_block(state: &mut [u32; 4], input: &[u8; 64]) { let mut a = state[0]; let mut b = state[1]; let mut c = state[2]; @@ -142,3 +156,10 @@ pub fn compress(state: &mut [u32; 4], input: &[u8; 64]) { state[2] = state[2].wrapping_add(c); state[3] = state[3].wrapping_add(d); } + +#[inline] +pub fn compress(state: &mut [u32; 4], blocks: &[[u8; 64]]) { + for block in blocks { + compress_block(state, block) + } +} diff --git a/md5/src/consts.rs b/md5/src/consts.rs deleted file mode 100644 index e9b94edb7..000000000 --- a/md5/src/consts.rs +++ /dev/null @@ -1,21 +0,0 @@ -#![allow(clippy::unreadable_literal)] - -/// Round constants -#[cfg(not(feature = "asm"))] -pub static RC: [u32; 64] = [ - // round 1 - 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, - 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, - // round 2 - 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, - 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, - // round 3 - 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, - 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, - // round 4 - 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, - 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, -]; - -/// Init state -pub const S0: [u32; 4] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476]; diff --git a/md5/src/lib.rs b/md5/src/lib.rs index 2bb9913d5..fadaf5192 100644 --- a/md5/src/lib.rs +++ b/md5/src/lib.rs @@ -25,102 +25,115 @@ #![no_std] #![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_root_url = "https://docs.rs/md-5/0.10.0" )] -#![deny(unsafe_code)] #![warn(missing_docs, rust_2018_idioms)] #[cfg(feature = "asm")] -extern crate md5_asm as utils; - -#[cfg(feature = "std")] -extern crate std; +extern crate md5_asm as compress; #[cfg(not(feature = "asm"))] -mod utils; +mod compress; pub use digest::{self, Digest}; -use crate::utils::compress; +use compress::compress; + +use core::{fmt, slice::from_ref}; +use digest::{ + block_buffer::Eager, + core_api::{ + AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore, + OutputSizeUser, Reset, UpdateCore, + }, + generic_array::typenum::{Unsigned, U16, U64}, + HashMarker, Output, +}; +/// Core MD5 hasher state. +#[derive(Clone)] +pub struct Md5Core { + block_len: u64, + state: [u32; 4], +} -use block_buffer::BlockBuffer; -use digest::generic_array::typenum::{U16, U64}; -use digest::generic_array::GenericArray; -use digest::{BlockInput, FixedOutputDirty, Reset, Update}; +impl HashMarker for Md5Core {} -mod consts; +impl BlockSizeUser for Md5Core { + type BlockSize = U64; +} -/// The MD5 hasher -#[derive(Clone)] -pub struct Md5 { - length_bytes: u64, - buffer: BlockBuffer, - state: [u32; 4], +impl BufferKindUser for Md5Core { + type BufferKind = Eager; } -impl Default for Md5 { - fn default() -> Self { - Md5 { - length_bytes: 0, - buffer: Default::default(), - state: consts::S0, - } - } +impl OutputSizeUser for Md5Core { + type OutputSize = U16; } -#[inline(always)] -fn convert(d: &GenericArray) -> &[u8; 64] { - #[allow(unsafe_code)] - unsafe { - &*(d.as_ptr() as *const [u8; 64]) +impl UpdateCore for Md5Core { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + self.block_len = self.block_len.wrapping_add(blocks.len() as u64); + compress(&mut self.state, convert(blocks)) } } -impl Md5 { +impl FixedOutputCore for Md5Core { #[inline] - fn finalize_inner(&mut self) { - let s = &mut self.state; - let l = (self.length_bytes << 3) as u64; - self.buffer.len64_padding_le(l, |d| compress(s, convert(d))); + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + let bit_len = self + .block_len + .wrapping_mul(Self::BlockSize::U64) + .wrapping_add(buffer.get_pos() as u64) + .wrapping_mul(8); + let mut s = self.state; + buffer.len64_padding_le(bit_len, |b| compress(&mut s, convert(from_ref(b)))); + for (chunk, v) in out.chunks_exact_mut(4).zip(s.iter()) { + chunk.copy_from_slice(&v.to_le_bytes()); + } } } -impl BlockInput for Md5 { - type BlockSize = U64; +impl Default for Md5Core { + #[inline] + fn default() -> Self { + Self { + block_len: 0, + state: [0x6745_2301, 0xEFCD_AB89, 0x98BA_DCFE, 0x1032_5476], + } + } } -impl Update for Md5 { +impl Reset for Md5Core { #[inline] - fn update(&mut self, input: impl AsRef<[u8]>) { - let input = input.as_ref(); - // Unlike Sha1 and Sha2, the length value in MD5 is defined as - // the length of the message mod 2^64 - ie: integer overflow is OK. - self.length_bytes = self.length_bytes.wrapping_add(input.len() as u64); - let s = &mut self.state; - self.buffer.input_block(input, |d| compress(s, convert(d))); + fn reset(&mut self) { + *self = Default::default(); } } -impl FixedOutputDirty for Md5 { - type OutputSize = U16; - - #[inline] - fn finalize_into_dirty(&mut self, out: &mut GenericArray) { - self.finalize_inner(); - for (chunk, v) in out.chunks_exact_mut(4).zip(self.state.iter()) { - chunk.copy_from_slice(&v.to_le_bytes()); - } +impl AlgorithmName for Md5Core { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Md5") } } -impl Reset for Md5 { - fn reset(&mut self) { - self.state = consts::S0; - self.length_bytes = 0; - self.buffer.reset(); +impl fmt::Debug for Md5Core { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Md5Core { ... }") } } -opaque_debug::implement!(Md5); -digest::impl_write!(Md5); +/// MD5 hasher state. +pub type Md5 = CoreWrapper; + +const BLOCK_SIZE: usize = ::BlockSize::USIZE; + +#[inline(always)] +fn convert(blocks: &[Block]) -> &[[u8; BLOCK_SIZE]] { + // SAFETY: GenericArray and [u8; 64] have + // exactly the same memory layout + let p = blocks.as_ptr() as *const [u8; BLOCK_SIZE]; + unsafe { core::slice::from_raw_parts(p, blocks.len()) } +} diff --git a/md5/tests/data/md5.blb b/md5/tests/data/md5.blb index 37f86c4c4..3f6d64383 100644 Binary files a/md5/tests/data/md5.blb and b/md5/tests/data/md5.blb differ diff --git a/ripemd/CHANGELOG.md b/ripemd/CHANGELOG.md new file mode 100644 index 000000000..56fbc112c --- /dev/null +++ b/ripemd/CHANGELOG.md @@ -0,0 +1,12 @@ +# 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). + +## 0.1.0 (2021-01-25) +- Initial release of merged `ripemd160` and `ripemd320` crates updated +to `digest` v0.10. ([#217]) + +[#217]: https://github.com/RustCrypto/hashes/pull/217 diff --git a/ripemd320/Cargo.toml b/ripemd/Cargo.toml similarity index 56% rename from ripemd320/Cargo.toml rename to ripemd/Cargo.toml index 6083fe0ef..9487f7fb9 100644 --- a/ripemd320/Cargo.toml +++ b/ripemd/Cargo.toml @@ -1,23 +1,21 @@ [package] -name = "ripemd320" -version = "0.9.0" -description = "RIPEMD-320 hash function" +name = "ripemd" +version = "0.1.0" # Also update html_root_url in lib.rs when bumping this +description = "Pure Rust implementation of the RIPEMD hash functions" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" readme = "README.md" edition = "2018" -documentation = "https://docs.rs/ripemd320" +documentation = "https://docs.rs/ripemd" repository = "https://github.com/RustCrypto/hashes" -keywords = ["crypto", "ripemd320", "hash", "digest"] +keywords = ["crypto", "ripemd", "hash", "digest"] categories = ["cryptography", "no-std"] [dependencies] -digest = "0.9" -block-buffer = "0.9" -opaque-debug = "0.3" +digest = "0.10" [dev-dependencies] -digest = { version = "0.9", features = ["dev"] } +digest = { version = "0.10", features = ["dev"] } hex-literal = "0.2" [features] diff --git a/ripemd256/LICENSE-APACHE b/ripemd/LICENSE-APACHE similarity index 100% rename from ripemd256/LICENSE-APACHE rename to ripemd/LICENSE-APACHE diff --git a/ripemd256/LICENSE-MIT b/ripemd/LICENSE-MIT similarity index 88% rename from ripemd256/LICENSE-MIT rename to ripemd/LICENSE-MIT index a239acf63..efb0b5f8b 100644 --- a/ripemd256/LICENSE-MIT +++ b/ripemd/LICENSE-MIT @@ -1,6 +1,4 @@ -Copyright (c) 2006-2009 Graydon Hoare -Copyright (c) 2009-2013 Mozilla Foundation -Copyright (c) 2016 The RustCrypto Project Developers +Copyright (c) 2021 RustCrypto Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/ripemd160/README.md b/ripemd/README.md similarity index 93% rename from ripemd160/README.md rename to ripemd/README.md index 29a18e4a0..64f72e493 100644 --- a/ripemd160/README.md +++ b/ripemd/README.md @@ -1,4 +1,4 @@ -# RustCrypto: RIPEMD160 +# RustCrypto: RIPEMD [![crate][crate-image]][crate-link] [![Docs][docs-image]][docs-link] @@ -7,7 +7,7 @@ [![Project Chat][chat-image]][chat-link] [![Build Status][build-image]][build-link] -Pure Rust implementation of the [RIPEMD160 hash function][1]. +Pure Rust implementation of the [RIPEMD] hash functions. [Documentation][docs-link] @@ -53,4 +53,4 @@ dual licensed as above, without any additional terms or conditions. [//]: # (general links) -[1]: https://en.wikipedia.org/wiki/RIPEMD +[RIPEMD]: https://en.wikipedia.org/wiki/RIPEMD diff --git a/ripemd/benches/ripemd160.rs b/ripemd/benches/ripemd160.rs new file mode 100644 index 000000000..618c30e8e --- /dev/null +++ b/ripemd/benches/ripemd160.rs @@ -0,0 +1,4 @@ +#![no_std] +#![feature(test)] + +digest::bench!(ripemd::Ripemd160); diff --git a/ripemd/benches/ripemd320.rs b/ripemd/benches/ripemd320.rs new file mode 100644 index 000000000..8a399a7ee --- /dev/null +++ b/ripemd/benches/ripemd320.rs @@ -0,0 +1,4 @@ +#![no_std] +#![feature(test)] + +digest::bench!(ripemd::Ripemd320); diff --git a/ripemd160/src/block.rs b/ripemd/src/c160.rs similarity index 98% rename from ripemd160/src/block.rs rename to ripemd/src/c160.rs index fccf1ab60..2163e848f 100644 --- a/ripemd160/src/block.rs +++ b/ripemd/src/c160.rs @@ -1,6 +1,5 @@ +use super::{Block, Ripemd160Core}; use core::convert::TryInto; -use digest::generic_array::typenum::U64; -use digest::generic_array::GenericArray; pub const DIGEST_BUF_LEN: usize = 5; pub const WORK_BUF_LEN: usize = 16; @@ -13,8 +12,6 @@ pub const H0: [u32; DIGEST_BUF_LEN] = [ 0xc3d2_e1f0, ]; -type Block = GenericArray; - macro_rules! round( ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $x:expr, $bits:expr, $add:expr, $round:expr) => ({ @@ -115,7 +112,7 @@ macro_rules! process_block( }); ); -pub fn process_msg_block(h: &mut [u32; DIGEST_BUF_LEN], data: &Block) { +pub fn compress(h: &mut [u32; DIGEST_BUF_LEN], data: &Block) { let mut w = [0u32; WORK_BUF_LEN]; for (o, chunk) in w.iter_mut().zip(data.chunks_exact(4)) { *o = u32::from_le_bytes(chunk.try_into().unwrap()); diff --git a/ripemd256/src/block.rs b/ripemd/src/c256.rs similarity index 98% rename from ripemd256/src/block.rs rename to ripemd/src/c256.rs index de085350c..a7d6e51a9 100644 --- a/ripemd256/src/block.rs +++ b/ripemd/src/c256.rs @@ -1,6 +1,5 @@ +use super::{Block, Ripemd256Core}; use core::{convert::TryInto, mem::swap}; -use digest::generic_array::typenum::U64; -use digest::generic_array::GenericArray; pub const DIGEST_BUF_LEN: usize = 8; pub const HALF_DIGEST_BUF_LEN: usize = DIGEST_BUF_LEN / 2; @@ -17,8 +16,6 @@ pub const H0: [u32; DIGEST_BUF_LEN] = [ 0x0123_4567, ]; -type Block = GenericArray; - macro_rules! round( ($a:expr, $b:expr, $c:expr, $d:expr, $x:expr, $bits:expr, $add:expr, $round:expr) => ({ @@ -122,7 +119,7 @@ macro_rules! process_block( }); ); -pub fn process_msg_block(h: &mut [u32; DIGEST_BUF_LEN], data: &Block) { +pub fn compress(h: &mut [u32; DIGEST_BUF_LEN], data: &Block) { let mut w = [0u32; WORK_BUF_LEN]; for (o, chunk) in w.iter_mut().zip(data.chunks_exact(4)) { *o = u32::from_le_bytes(chunk.try_into().unwrap()); diff --git a/ripemd320/src/block.rs b/ripemd/src/c320.rs similarity index 98% rename from ripemd320/src/block.rs rename to ripemd/src/c320.rs index 4834ead90..89b174066 100644 --- a/ripemd320/src/block.rs +++ b/ripemd/src/c320.rs @@ -1,6 +1,5 @@ +use super::{Block, Ripemd320Core}; use core::{convert::TryInto, mem::swap}; -use digest::generic_array::typenum::U64; -use digest::generic_array::GenericArray; pub const HALF_DIGEST_BUF_LEN: usize = 5; pub const DIGEST_BUF_LEN: usize = 10; @@ -19,8 +18,6 @@ pub const H0: [u32; DIGEST_BUF_LEN] = [ 0x3c2d_1e0f, ]; -type Block = GenericArray; - macro_rules! round( ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $x:expr, $bits:expr, $add:expr, $round:expr) => ({ @@ -145,7 +142,7 @@ macro_rules! process_block( }); ); -pub fn process_msg_block(h: &mut [u32; DIGEST_BUF_LEN], data: &Block) { +pub fn compress(h: &mut [u32; DIGEST_BUF_LEN], data: &Block) { let mut w = [0u32; WORK_BUF_LEN]; for (o, chunk) in w.iter_mut().zip(data.chunks_exact(4)) { *o = u32::from_le_bytes(chunk.try_into().unwrap()); diff --git a/ripemd/src/lib.rs b/ripemd/src/lib.rs new file mode 100644 index 000000000..c428d4f12 --- /dev/null +++ b/ripemd/src/lib.rs @@ -0,0 +1,299 @@ +//! An implementation of the [RIPEMD] cryptographic hash. +//! +//! This crate implements only the modified 1996 versions, not the original +//! one from 1992. +//! +//! Note that RIPEMD-256 provides only the same security as RIPEMD-128, +//! and RIPEMD-320 provides only the same security as RIPEMD-160. +//! +//! # Usage +//! +//! ```rust +//! use hex_literal::hex; +//! use ripemd::{Ripemd160, Ripemd320, Digest}; +//! +//! // create a RIPEMD-160 hasher instance +//! let mut hasher = Ripemd160::new(); +//! +//! // process input message +//! hasher.update(b"Hello world!"); +//! +//! // acquire hash digest in the form of GenericArray, +//! // which in this case is equivalent to [u8; 20] +//! let result = hasher.finalize(); +//! assert_eq!(result[..], hex!("7f772647d88750add82d8e1a7a3e5c0902a346a3")); +//! +//! // same for RIPEMD-320 +//! let mut hasher = Ripemd320::new(); +//! hasher.update(b"Hello world!"); +//! let result = hasher.finalize(); +//! assert_eq!(&result[..], &hex!(" +//! f1c1c231d301abcf2d7daae0269ff3e7bc68e623 +//! ad723aa068d316b056d26b7d1bb6f0cc0f28336d +//! ")[..]); +//! ``` +//! +//! Also see [RustCrypto/hashes] readme. +//! +//! [RIPEMD]: https://en.wikipedia.org/wiki/RIPEMD +//! [RustCrypto/hashes]: https://github.com/RustCrypto/hashes + +#![no_std] +#![doc( + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_root_url = "https://docs.rs/ripemd/0.1.0" +)] +#![deny(unsafe_code)] +#![warn(missing_docs, rust_2018_idioms)] + +pub use digest::{self, Digest}; + +use core::fmt; +use digest::{ + block_buffer::Eager, + core_api::{ + AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore, + OutputSizeUser, Reset, UpdateCore, + }, + generic_array::typenum::{Unsigned, U20, U32, U40, U64}, + HashMarker, Output, +}; + +mod c160; +mod c256; +mod c320; + +/// Core RIPEMD-160 hasher state. +#[derive(Clone)] +pub struct Ripemd160Core { + h: [u32; c160::DIGEST_BUF_LEN], + block_len: u64, +} + +impl HashMarker for Ripemd160Core {} + +impl BlockSizeUser for Ripemd160Core { + type BlockSize = U64; +} + +impl BufferKindUser for Ripemd160Core { + type BufferKind = Eager; +} + +impl OutputSizeUser for Ripemd160Core { + type OutputSize = U20; +} + +impl UpdateCore for Ripemd160Core { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + // Assumes that `block_len` does not overflow + self.block_len += blocks.len() as u64; + for block in blocks { + c160::compress(&mut self.h, block); + } + } +} + +impl FixedOutputCore for Ripemd160Core { + #[inline] + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + let bs = Self::BlockSize::U64; + let bit_len = 8 * (buffer.get_pos() as u64 + bs * self.block_len); + let mut h = self.h; + buffer.len64_padding_le(bit_len, |block| c160::compress(&mut h, block)); + + for (chunk, v) in out.chunks_exact_mut(4).zip(h.iter()) { + chunk.copy_from_slice(&v.to_le_bytes()); + } + } +} + +impl Default for Ripemd160Core { + #[inline] + fn default() -> Self { + Self { + h: c160::H0, + block_len: 0, + } + } +} + +impl Reset for Ripemd160Core { + #[inline] + fn reset(&mut self) { + *self = Default::default(); + } +} + +impl AlgorithmName for Ripemd160Core { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Ripemd160") + } +} + +impl fmt::Debug for Ripemd160Core { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Ripemd160Core { ... }") + } +} + +/// RIPEMD-160 hasher state. +pub type Ripemd160 = CoreWrapper; + +/// Core RIPEMD-256 hasher state. +#[derive(Clone)] +pub struct Ripemd256Core { + h: [u32; c256::DIGEST_BUF_LEN], + block_len: u64, +} + +impl HashMarker for Ripemd256Core {} + +impl BlockSizeUser for Ripemd256Core { + type BlockSize = U64; +} + +impl BufferKindUser for Ripemd256Core { + type BufferKind = Eager; +} + +impl OutputSizeUser for Ripemd256Core { + type OutputSize = U32; +} + +impl UpdateCore for Ripemd256Core { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + // Assumes that `block_len` does not overflow + self.block_len += blocks.len() as u64; + for block in blocks { + c256::compress(&mut self.h, block); + } + } +} + +impl FixedOutputCore for Ripemd256Core { + #[inline] + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + let bs = Self::BlockSize::U64; + let bit_len = 8 * (buffer.get_pos() as u64 + bs * self.block_len); + let mut h = self.h; + buffer.len64_padding_le(bit_len, |block| c256::compress(&mut h, block)); + + for (chunk, v) in out.chunks_exact_mut(4).zip(h.iter()) { + chunk.copy_from_slice(&v.to_le_bytes()); + } + } +} + +impl Default for Ripemd256Core { + #[inline] + fn default() -> Self { + Self { + h: c256::H0, + block_len: 0, + } + } +} + +impl Reset for Ripemd256Core { + #[inline] + fn reset(&mut self) { + *self = Default::default(); + } +} + +impl AlgorithmName for Ripemd256Core { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Ripemd256") + } +} + +impl fmt::Debug for Ripemd256Core { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Ripemd256Core { ... }") + } +} + +/// RIPEMD-160 hasher state. +pub type Ripemd256 = CoreWrapper; + +/// Core RIPEMD-320 hasher state. +#[derive(Clone)] +pub struct Ripemd320Core { + h: [u32; c320::DIGEST_BUF_LEN], + block_len: u64, +} + +impl HashMarker for Ripemd320Core {} + +impl BlockSizeUser for Ripemd320Core { + type BlockSize = U64; +} + +impl BufferKindUser for Ripemd320Core { + type BufferKind = Eager; +} + +impl OutputSizeUser for Ripemd320Core { + type OutputSize = U40; +} + +impl UpdateCore for Ripemd320Core { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + // Assumes that `block_len` does not overflow + self.block_len += blocks.len() as u64; + for block in blocks { + c320::compress(&mut self.h, block); + } + } +} + +impl FixedOutputCore for Ripemd320Core { + #[inline] + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + let bs = Self::BlockSize::U64; + let bit_len = 8 * (buffer.get_pos() as u64 + bs * self.block_len); + let mut h = self.h; + buffer.len64_padding_le(bit_len, |block| c320::compress(&mut h, block)); + + for (chunk, v) in out.chunks_exact_mut(4).zip(h.iter()) { + chunk.copy_from_slice(&v.to_le_bytes()); + } + } +} + +impl Default for Ripemd320Core { + #[inline] + fn default() -> Self { + Self { + h: c320::H0, + block_len: 0, + } + } +} + +impl Reset for Ripemd320Core { + #[inline] + fn reset(&mut self) { + *self = Default::default(); + } +} + +impl AlgorithmName for Ripemd320Core { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Ripemd320") + } +} + +impl fmt::Debug for Ripemd320Core { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Ripemd320Core { ... }") + } +} + +/// RIPEMD-320 hasher state. +pub type Ripemd320 = CoreWrapper; diff --git a/ripemd/tests/data/ripemd160.blb b/ripemd/tests/data/ripemd160.blb new file mode 100644 index 000000000..ee23310ad Binary files /dev/null and b/ripemd/tests/data/ripemd160.blb differ diff --git a/ripemd/tests/data/ripemd256.blb b/ripemd/tests/data/ripemd256.blb new file mode 100644 index 000000000..733bc5772 Binary files /dev/null and b/ripemd/tests/data/ripemd256.blb differ diff --git a/ripemd/tests/data/ripemd320.blb b/ripemd/tests/data/ripemd320.blb new file mode 100644 index 000000000..cf006b8b1 Binary files /dev/null and b/ripemd/tests/data/ripemd320.blb differ diff --git a/ripemd/tests/lib.rs b/ripemd/tests/lib.rs new file mode 100644 index 000000000..9edf6f32e --- /dev/null +++ b/ripemd/tests/lib.rs @@ -0,0 +1,32 @@ +//! Test vectors from FIPS 180-1 and from the [RIPEMD webpage][1]. +//! +//! [1] https://homes.esat.kuleuven.be/~bosselae/ripemd160.html + +use digest::dev::{digest_test, one_million_a}; +use digest::new_test; +use hex_literal::hex; +use ripemd::{Ripemd160, Ripemd256, Ripemd320}; + +new_test!(ripemd160_main, "ripemd160", Ripemd160, digest_test); +new_test!(ripemd256_main, "ripemd256", Ripemd256, digest_test); +new_test!(ripemd320_main, "ripemd320", Ripemd320, digest_test); + +#[test] +fn ripemd160_1million_a() { + let expected = hex!("52783243c1697bdbe16d37f97f68f08325dc1528"); + one_million_a::(&expected); +} + +#[test] +fn ripemd256_1million_a() { + one_million_a::(&hex!( + "ac953744e10e31514c150d4d8d7b677342e33399788296e43ae4850ce4f97978" + )); +} + +#[test] +fn ripemd320_1million_a() { + let expected = + hex!("bdee37f4371e20646b8b0d862dda16292ae36f40965e8c8509e63d1dbddecc503e2b63eb9245bb66"); + one_million_a::(&expected); +} diff --git a/ripemd160/CHANGELOG.md b/ripemd160/CHANGELOG.md deleted file mode 100644 index 22305f2b8..000000000 --- a/ripemd160/CHANGELOG.md +++ /dev/null @@ -1,50 +0,0 @@ -# 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). - -## 0.9.1 (2020-06-28) -### Changed -- Update to `block-buffer` v0.9 ([#164]) -- Update to `opaque-debug` v0.3 ([#168]) - -[#164]: https://github.com/RustCrypto/hashes/pull/164 -[#168]: https://github.com/RustCrypto/hashes/pull/168 - -## 0.9.0 (2020-06-10) -### Changed -- Update to `digest` v0.9 release ([#155]) -- Use new `*Dirty` traits from the `digest` crate ([#153]) -- Bump `block-buffer` to v0.8 release ([#151]) -- Rename `*result*` to `finalize` ([#148]) -- Upgrade to Rust 2018 edition ([#129]) - -[#155]: https://github.com/RustCrypto/hashes/pull/155 -[#153]: https://github.com/RustCrypto/hashes/pull/153 -[#151]: https://github.com/RustCrypto/hashes/pull/151 -[#148]: https://github.com/RustCrypto/hashes/pull/148 -[#129]: https://github.com/RustCrypto/hashes/pull/129 - -## 0.8.0 (2018-10-02) - -## 0.7.0 (2017-11-15) - -## 0.6.0 (2017-06-12) - -## 0.5.2 (2017-06-04) - -## 0.5.1 (2017-05-02) - -## 0.5.0 (2017-04-06) - -## 0.4.1 (2017-01-20) - -## 0.4.0 (2016-12-25) - -## 0.3.0 (2016-11-17) - -## 0.2.0 (2016-10-14) - -## 0.1.0 (2016-10-06) diff --git a/ripemd160/Cargo.toml b/ripemd160/Cargo.toml deleted file mode 100644 index 9f1861621..000000000 --- a/ripemd160/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -name = "ripemd160" -version = "0.9.1" -description = "RIPEMD-160 hash function" -authors = ["RustCrypto Developers"] -license = "MIT OR Apache-2.0" -readme = "README.md" -edition = "2018" -documentation = "https://docs.rs/ripemd160" -repository = "https://github.com/RustCrypto/hashes" -keywords = ["crypto", "ripemd160", "hash", "digest"] -categories = ["cryptography", "no-std"] - -[dependencies] -digest = "0.9" -block-buffer = "0.9" -opaque-debug = "0.3" - -[dev-dependencies] -digest = { version = "0.9", features = ["dev"] } -hex-literal = "0.2" - -[features] -default = ["std"] -std = ["digest/std"] diff --git a/ripemd160/benches/lib.rs b/ripemd160/benches/lib.rs deleted file mode 100644 index c665c0793..000000000 --- a/ripemd160/benches/lib.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![no_std] -#![feature(test)] - -digest::bench!(ripemd160::Ripemd160); diff --git a/ripemd160/examples/ripemd160sum.rs b/ripemd160/examples/ripemd160sum.rs deleted file mode 100644 index 4f71a12af..000000000 --- a/ripemd160/examples/ripemd160sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use ripemd160::{Digest, Ripemd160}; -use std::env; -use std::fs; -use std::io::{self, Read}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = D::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/ripemd160/src/lib.rs b/ripemd160/src/lib.rs deleted file mode 100644 index 544d4ae2e..000000000 --- a/ripemd160/src/lib.rs +++ /dev/null @@ -1,101 +0,0 @@ -//! An implementation of the [RIPEMD-160][1] cryptographic hash. -//! -//! # Usage -//! -//! ```rust -//! use hex_literal::hex; -//! use ripemd160::{Ripemd160, Digest}; -//! -//! // create a RIPEMD-160 hasher instance -//! let mut hasher = Ripemd160::new(); -//! -//! // process input message -//! hasher.update(b"Hello world!"); -//! -//! // acquire hash digest in the form of GenericArray, -//! // which in this case is equivalent to [u8; 20] -//! let result = hasher.finalize(); -//! assert_eq!(result[..], hex!("7f772647d88750add82d8e1a7a3e5c0902a346a3")); -//! ``` -//! -//! Also see [RustCrypto/hashes][2] readme. -//! -//! [1]: https://en.wikipedia.org/wiki/RIPEMD -//! [2]: https://github.com/RustCrypto/hashes - -#![no_std] -#![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" -)] -#![deny(unsafe_code)] -#![warn(missing_docs, rust_2018_idioms)] - -#[cfg(feature = "std")] -extern crate std; - -mod block; - -pub use digest::{self, Digest}; - -use crate::block::{process_msg_block, DIGEST_BUF_LEN, H0}; -use block_buffer::BlockBuffer; -use digest::consts::{U20, U64}; -use digest::{BlockInput, FixedOutputDirty, Reset, Update}; - -/// Structure representing the state of a Ripemd160 computation -#[derive(Clone)] -pub struct Ripemd160 { - h: [u32; DIGEST_BUF_LEN], - len: u64, - buffer: BlockBuffer, -} - -impl Default for Ripemd160 { - fn default() -> Self { - Ripemd160 { - h: H0, - len: 0, - buffer: Default::default(), - } - } -} - -impl BlockInput for Ripemd160 { - type BlockSize = U64; -} - -impl Update for Ripemd160 { - fn update(&mut self, input: impl AsRef<[u8]>) { - let input = input.as_ref(); - // Assumes that input.len() can be converted to u64 without overflow - self.len += input.len() as u64; - let h = &mut self.h; - self.buffer.input_block(input, |b| process_msg_block(h, b)); - } -} - -impl FixedOutputDirty for Ripemd160 { - type OutputSize = U20; - - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - let h = &mut self.h; - let l = self.len << 3; - self.buffer.len64_padding_le(l, |b| process_msg_block(h, b)); - - for (chunk, v) in out.chunks_exact_mut(4).zip(self.h.iter()) { - chunk.copy_from_slice(&v.to_le_bytes()); - } - } -} - -impl Reset for Ripemd160 { - fn reset(&mut self) { - self.buffer.reset(); - self.len = 0; - self.h = H0; - } -} - -opaque_debug::implement!(Ripemd160); -digest::impl_write!(Ripemd160); diff --git a/ripemd160/tests/data/one_million_a.bin b/ripemd160/tests/data/one_million_a.bin deleted file mode 100644 index df1956351..000000000 --- a/ripemd160/tests/data/one_million_a.bin +++ /dev/null @@ -1 +0,0 @@ -Rx2Ci{m7h%( \ No newline at end of file diff --git a/ripemd160/tests/data/ripemd160.blb b/ripemd160/tests/data/ripemd160.blb deleted file mode 100644 index c3ce45f16..000000000 --- a/ripemd160/tests/data/ripemd160.blb +++ /dev/null @@ -1 +0,0 @@ -blobby1abc]zJưZ 8abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopqS8J l'b++The quick brown fox jumps over the lazy dog72{Ԗqg;+The quick brown fox jumps over the lazy cog ri 3^ wJ \ No newline at end of file diff --git a/ripemd160/tests/lib.rs b/ripemd160/tests/lib.rs deleted file mode 100644 index ccb7bce78..000000000 --- a/ripemd160/tests/lib.rs +++ /dev/null @@ -1,18 +0,0 @@ -//! Test messages from FIPS 180-1 -#![no_std] - -use digest::dev::{digest_test, one_million_a}; -use digest::new_test; - -new_test!( - ripemd160_main, - "ripemd160", - ripemd160::Ripemd160, - digest_test -); - -#[test] -fn ripemd160_1million_a() { - let output = include_bytes!("data/one_million_a.bin"); - one_million_a::(output); -} diff --git a/ripemd256/.gitignore b/ripemd256/.gitignore deleted file mode 100644 index 96ef6c0b9..000000000 --- a/ripemd256/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -Cargo.lock diff --git a/ripemd256/Cargo.toml b/ripemd256/Cargo.toml deleted file mode 100644 index 67fe29899..000000000 --- a/ripemd256/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -name = "ripemd256" -version = "0.1.0" -authors = ["RustCrypto Developers"] -license = "MIT OR Apache-2.0" -edition = "2018" -readme = "README.md" -keywords = ["crypto", "ripemd256", "hash", "digest"] -categories = ["cryptography", "no-std"] -description = "RIPEMD-256 hash function" -repository = "https://github.com/RustCrypto/hashes" - - -[dependencies] -block-buffer = "0.9" -digest = "0.9" -opaque-debug = "0.3" - -[dev-dependencies] -digest = { version = "0.9", features = ["dev"] } -hex-literal = "0.2" - -[features] -default = ["std"] -std = ["digest/std"] diff --git a/ripemd256/README.md b/ripemd256/README.md deleted file mode 100644 index b0bab35e7..000000000 --- a/ripemd256/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# RustCrypto: RIPEMD256 -Pure Rust implementation of the [RIPEMD256 hash function][1]. - -## Minimum Supported Rust Version - -Rust **1.41** or higher. - -Minimum supported Rust version can be changed in the future, but it will be -done with a minor version bump. - -## SemVer Policy - -- All on-by-default features of this library are covered by SemVer -- MSRV is considered exempt from SemVer as noted above - -## License - -Licensed under either of: - - * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) - * [MIT license](http://opensource.org/licenses/MIT) - -at your option. - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in the work by you, as defined in the Apache-2.0 license, shall be -dual licensed as above, without any additional terms or conditions - -[1]: https://en.wikipedia.org/wiki/RIPEMD diff --git a/ripemd256/examples/ripemd256sum.rs b/ripemd256/examples/ripemd256sum.rs deleted file mode 100644 index 6a6ad1a5c..000000000 --- a/ripemd256/examples/ripemd256sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use ripemd256::{Digest, Ripemd256}; -use std::env; -use std::fs; -use std::io::{self, Read}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = D::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/ripemd256/src/lib.rs b/ripemd256/src/lib.rs deleted file mode 100644 index 70b6344a7..000000000 --- a/ripemd256/src/lib.rs +++ /dev/null @@ -1,96 +0,0 @@ -//! An implementation of the [RIPEMD-256][1] cryptographic hash. -//! -//! # Usage -//! -//! ```rust -//! use hex_literal::hex; -//! use ripemd256::{Ripemd256, Digest}; -//! -//! // create a RIPEMD-256 hasher instance -//! let mut hasher = Ripemd256::new(); -//! -//! // process input message -//! hasher.update(b"Hello world!"); -//! -//! // acquire hash digest in the form of GenericArray, -//! // which in this case is equivalent to [u8; 32] -//! let expected = hex!("2700f1122c7bd5df165b0615efbbbc54f551aef2401738811a5aea19ccb9233a"); -//! let result = hasher.finalize(); -//! assert_eq!(&result[..], &expected[..]); -//! ``` -//! -//! [1]: https://en.wikipedia.org/wiki/RIPEMD - -#![no_std] -#![deny(unsafe_code)] -#![warn(missing_docs, rust_2018_idioms)] - -#[cfg(feature = "std")] -extern crate std; - -mod block; - -pub use digest::{self, Digest}; - -use block::{process_msg_block, DIGEST_BUF_LEN, H0}; -use block_buffer::BlockBuffer; -use digest::{ - consts::{U32, U64}, - BlockInput, FixedOutputDirty, Reset, Update, -}; - -/// Structure representing the state of a Ripemd256 computation -#[derive(Clone)] -pub struct Ripemd256 { - h: [u32; DIGEST_BUF_LEN], - len: u64, - buffer: BlockBuffer, -} - -impl Default for Ripemd256 { - fn default() -> Self { - Ripemd256 { - h: H0, - len: 0, - buffer: Default::default(), - } - } -} - -impl BlockInput for Ripemd256 { - type BlockSize = U64; -} - -impl Update for Ripemd256 { - fn update(&mut self, input: impl AsRef<[u8]>) { - let input = input.as_ref(); - // Assumes that input.len() can be converted to u64 without overflow - self.len += input.len() as u64; - let h = &mut self.h; - self.buffer.input_block(input, |b| process_msg_block(h, b)); - } -} - -impl FixedOutputDirty for Ripemd256 { - type OutputSize = U32; - - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - let h = &mut self.h; - let l = self.len << 3; - self.buffer.len64_padding_le(l, |b| process_msg_block(h, b)); - for (chunk, v) in out.chunks_exact_mut(4).zip(self.h.iter()) { - chunk.copy_from_slice(&v.to_le_bytes()); - } - } -} - -impl Reset for Ripemd256 { - fn reset(&mut self) { - self.buffer.reset(); - self.len = 0; - self.h = H0; - } -} - -opaque_debug::implement!(Ripemd256); -digest::impl_write!(Ripemd256); diff --git a/ripemd256/tests/lib.rs b/ripemd256/tests/lib.rs deleted file mode 100644 index 099ad9968..000000000 --- a/ripemd256/tests/lib.rs +++ /dev/null @@ -1,53 +0,0 @@ -use digest::dev::one_million_a; -use hex_literal::hex; -use ripemd256::{Digest, Ripemd256}; - -fn hash_test(msg: &str, expected: [u8; 32]) { - let mut hasher = Ripemd256::new(); - hasher.update(msg.as_bytes()); - let result = hasher.finalize(); - assert_eq!(result[..], expected); -} - -#[test] -fn ripemd256_messages() { - hash_test( - "", - hex!("02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d"), - ); - hash_test( - "a", - hex!("f9333e45d857f5d90a91bab70a1eba0cfb1be4b0783c9acfcd883a9134692925"), - ); - hash_test( - "abc", - hex!("afbd6e228b9d8cbbcef5ca2d03e6dba10ac0bc7dcbe4680e1e42d2e975459b65"), - ); - hash_test( - "message digest", - hex!("87e971759a1ce47a514d5c914c392c9018c7c46bc14465554afcdf54a5070c0e"), - ); - hash_test( - "abcdefghijklmnopqrstuvwxyz", - hex!("649d3034751ea216776bf9a18acc81bc7896118a5197968782dd1fd97d8d5133"), - ); - hash_test( - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - hex!("3843045583aac6c8c8d9128573e7a9809afb2a0f34ccc36ea9e72f16f6368e3f"), - ); - hash_test( - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - hex!("5740a408ac16b720b84424ae931cbb1fe363d1d0bf4017f1a89f7ea6de77a0b8"), - ); - hash_test( - "12345678901234567890123456789012345678901234567890123456789012345678901234567890", - hex!("06fdcc7a409548aaf91368c06a6275b553e3f099bf0ea4edfd6778df89a890dd"), - ); -} - -#[test] -fn ripemd256_1million_a() { - one_million_a::(&hex!( - "ac953744e10e31514c150d4d8d7b677342e33399788296e43ae4850ce4f97978" - )); -} diff --git a/ripemd320/CHANGELOG.md b/ripemd320/CHANGELOG.md deleted file mode 100644 index 58dfc426a..000000000 --- a/ripemd320/CHANGELOG.md +++ /dev/null @@ -1,25 +0,0 @@ -# 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). - -## 0.9.0 (2020-06-12) -### Changed -- Bump `opaque-debug` to v0.3.0 ([#168]) -- Bump `digest` to v0.9 release; MSRV 1.41 ([#155]) -- Use new `*Dirty` traits from the `digest` crate ([#153]) -- Bump `block-buffer` to v0.8 release ([#151]) -- Rename `*result*` to `finalize` ([#148]) -- Upgrade to Rust 2018 edition ([#130]) - -[#168]: https://github.com/RustCrypto/hashes/pull/168 -[#155]: https://github.com/RustCrypto/hashes/pull/155 -[#153]: https://github.com/RustCrypto/hashes/pull/153 -[#151]: https://github.com/RustCrypto/hashes/pull/151 -[#148]: https://github.com/RustCrypto/hashes/pull/148 -[#130]: https://github.com/RustCrypto/hashes/pull/130 - -## 0.8.0 (2019-02-11) -- Initial release diff --git a/ripemd320/LICENSE-APACHE b/ripemd320/LICENSE-APACHE deleted file mode 100644 index 78173fa2e..000000000 --- a/ripemd320/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/ripemd320/LICENSE-MIT b/ripemd320/LICENSE-MIT deleted file mode 100644 index a239acf63..000000000 --- a/ripemd320/LICENSE-MIT +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2006-2009 Graydon Hoare -Copyright (c) 2009-2013 Mozilla Foundation -Copyright (c) 2016 The RustCrypto Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/ripemd320/README.md b/ripemd320/README.md deleted file mode 100644 index ba34c4c46..000000000 --- a/ripemd320/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# RustCrypto: RIPEMD320 - -[![crate][crate-image]][crate-link] -[![Docs][docs-image]][docs-link] -![Apache2/MIT licensed][license-image] -![Rust Version][rustc-image] -[![Project Chat][chat-image]][chat-link] -[![Build Status][build-image]][build-link] - -Pure Rust implementation of the [RIPEMD320 hash function][1]. - -[Documentation][docs-link] - -## Minimum Supported Rust Version - -Rust **1.41** or higher. - -Minimum supported Rust version can be changed in the future, but it will be -done with a minor version bump. - -## SemVer Policy - -- All on-by-default features of this library are covered by SemVer -- MSRV is considered exempt from SemVer as noted above - -## License - -Licensed under either of: - - * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) - * [MIT license](http://opensource.org/licenses/MIT) - -at your option. - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in the work by you, as defined in the Apache-2.0 license, shall be -dual licensed as above, without any additional terms or conditions. - -[//]: # (badges) - -[crate-image]: https://img.shields.io/crates/v/ripemd320.svg -[crate-link]: https://crates.io/crates/ripemd320 -[docs-image]: https://docs.rs/ripemd320/badge.svg -[docs-link]: https://docs.rs/ripemd320/ -[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg -[rustc-image]: https://img.shields.io/badge/rustc-1.41+-blue.svg -[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg -[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260041-hashes -[build-image]: https://github.com/RustCrypto/hashes/workflows/ripemd320/badge.svg?branch=master -[build-link]: https://github.com/RustCrypto/hashes/actions?query=workflow%3Aripemd320 - -[//]: # (general links) - -[1]: https://en.wikipedia.org/wiki/RIPEMD diff --git a/ripemd320/benches/lib.rs b/ripemd320/benches/lib.rs deleted file mode 100644 index c8e49596b..000000000 --- a/ripemd320/benches/lib.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![no_std] -#![feature(test)] - -digest::bench!(ripemd320::Ripemd320); diff --git a/ripemd320/examples/ripemd320sum.rs b/ripemd320/examples/ripemd320sum.rs deleted file mode 100644 index 0b1f49fa3..000000000 --- a/ripemd320/examples/ripemd320sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use ripemd320::{Digest, Ripemd320}; -use std::env; -use std::fs; -use std::io::{self, Read}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = D::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/ripemd320/src/lib.rs b/ripemd320/src/lib.rs deleted file mode 100644 index ba6f32ce0..000000000 --- a/ripemd320/src/lib.rs +++ /dev/null @@ -1,102 +0,0 @@ -//! An implementation of the [RIPEMD-320][1] cryptographic hash. -//! -//! # Usage -//! -//! ```rust -//! use hex_literal::hex; -//! use ripemd320::{Ripemd320, Digest}; -//! -//! // create a RIPEMD-320 hasher instance -//! let mut hasher = Ripemd320::new(); -//! -//! // process input message -//! hasher.update(b"Hello world!"); -//! -//! // acquire hash digest in the form of GenericArray, -//! // which in this case is equivalent to [u8; 40] -//! let expected = hex!("f1c1c231d301abcf2d7daae0269ff3e7bc68e623ad723aa068d316b056d26b7d1bb6f0cc0f28336d"); -//! let result = hasher.finalize(); -//! assert_eq!(&result[..], &expected[..]); -//! ``` -//! -//! Also see [RustCrypto/hashes][2] readme. -//! -//! [1]: https://en.wikipedia.org/wiki/RIPEMD -//! [2]: https://github.com/RustCrypto/hashes - -#![no_std] -#![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" -)] -#![deny(unsafe_code)] -#![warn(missing_docs, rust_2018_idioms)] - -#[cfg(feature = "std")] -extern crate std; - -mod block; - -pub use digest::{self, Digest}; - -use crate::block::{process_msg_block, DIGEST_BUF_LEN, H0}; - -use block_buffer::BlockBuffer; -use digest::consts::{U40, U64}; -use digest::{BlockInput, FixedOutputDirty, Reset, Update}; - -/// Structure representing the state of a ripemd320 computation -#[derive(Clone)] -pub struct Ripemd320 { - h: [u32; DIGEST_BUF_LEN], - len: u64, - buffer: BlockBuffer, -} - -impl Default for Ripemd320 { - fn default() -> Self { - Ripemd320 { - h: H0, - len: 0, - buffer: Default::default(), - } - } -} - -impl BlockInput for Ripemd320 { - type BlockSize = U64; -} - -impl Update for Ripemd320 { - fn update(&mut self, input: impl AsRef<[u8]>) { - let input = input.as_ref(); - // Assumes that input.len() can be converted to u64 without overflow - self.len += input.len() as u64; - let h = &mut self.h; - self.buffer.input_block(input, |b| process_msg_block(h, b)); - } -} - -impl FixedOutputDirty for Ripemd320 { - type OutputSize = U40; - - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - let h = &mut self.h; - let l = self.len << 3; - self.buffer.len64_padding_le(l, |b| process_msg_block(h, b)); - for (chunk, v) in out.chunks_exact_mut(4).zip(self.h.iter()) { - chunk.copy_from_slice(&v.to_le_bytes()); - } - } -} - -impl Reset for Ripemd320 { - fn reset(&mut self) { - self.buffer.reset(); - self.len = 0; - self.h = H0; - } -} - -opaque_debug::implement!(Ripemd320); -digest::impl_write!(Ripemd320); diff --git a/ripemd320/tests/data/one_million_a.bin b/ripemd320/tests/data/one_million_a.bin deleted file mode 100644 index ebf119470..000000000 --- a/ripemd320/tests/data/one_million_a.bin +++ /dev/null @@ -1 +0,0 @@ -77 dk -)*o@^ =P>+cEf \ No newline at end of file diff --git a/ripemd320/tests/data/ripemd320.blb b/ripemd320/tests/data/ripemd320.blb deleted file mode 100644 index 2b5f1d993..000000000 Binary files a/ripemd320/tests/data/ripemd320.blb and /dev/null differ diff --git a/ripemd320/tests/lib.rs b/ripemd320/tests/lib.rs deleted file mode 100644 index 727131595..000000000 --- a/ripemd320/tests/lib.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! Test messages from FIPS 180-1 and from the RIPEMD-160 webpage[1] -//! [1] https://homes.esat.kuleuven.be/~bosselae/ripemd160.html -#![no_std] - -use digest::dev::{digest_test, one_million_a}; -use digest::new_test; - -new_test!( - ripemd320_main, - "ripemd320", - ripemd320::Ripemd320, - digest_test -); - -#[test] -fn ripemd320_1million_a() { - let output = include_bytes!("data/one_million_a.bin"); - one_million_a::(&output[..]); -} diff --git a/sha1/CHANGELOG.md b/sha1/CHANGELOG.md index 17cd4b9e9..0a7eb63a4 100644 --- a/sha1/CHANGELOG.md +++ b/sha1/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## 0.10.0 (2021-11-22) +### Changed +- Update to `digest` v0.10 ([#217]) + +[#217]: https://github.com/RustCrypto/hashes/pull/217 + ## 0.9.8 (2021-08-27) ### Changed - Bump `cpufeatures` dependency to 0.2 ([#306]) diff --git a/sha1/Cargo.toml b/sha1/Cargo.toml index cbf261eca..3c8c14624 100644 --- a/sha1/Cargo.toml +++ b/sha1/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sha-1" -version = "0.9.8" +version = "0.10.0" # Also update html_root_url in lib.rs when bumping this description = "SHA-1 hash function" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -15,9 +15,7 @@ categories = ["cryptography", "no-std"] name = "sha1" [dependencies] -digest = "0.9" -block-buffer = "0.9" -opaque-debug = "0.3" +digest = "0.10" cfg-if = "1.0" sha1-asm = { version = "0.5", optional = true } @@ -25,7 +23,7 @@ sha1-asm = { version = "0.5", optional = true } cpufeatures = "0.2" [dev-dependencies] -digest = { version = "0.9", features = ["dev"] } +digest = { version = "0.10", features = ["dev"] } hex-literal = "0.2" [features] @@ -35,9 +33,6 @@ asm = ["sha1-asm"] compress = [] # Expose compress function force-soft = [] # Force software implementation -# DEPRECATED: use `asm` instead -asm-aarch64 = ["asm"] - [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] diff --git a/sha1/examples/sha1sum.rs b/sha1/examples/sha1sum.rs deleted file mode 100644 index 78d0cbf90..000000000 --- a/sha1/examples/sha1sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use sha1::{Digest, Sha1}; -use std::env; -use std::fs; -use std::io::{self, Read}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = D::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/sha1/src/compress.rs b/sha1/src/compress.rs index b45f87bc2..feba6fd05 100644 --- a/sha1/src/compress.rs +++ b/sha1/src/compress.rs @@ -1,5 +1,5 @@ -use digest::consts::U64; -use digest::generic_array::GenericArray; +use crate::{Block, BlockSizeUser, Sha1Core}; +use digest::generic_array::typenum::Unsigned; cfg_if::cfg_if! { if #[cfg(feature = "force-soft")] { @@ -14,9 +14,7 @@ cfg_if::cfg_if! { mod soft; #[cfg(feature = "asm")] mod soft { - pub(crate) fn compress(state: &mut [u32; 5], blocks: &[[u8; 64]]) { - sha1_asm::compress(state, blocks) - } + pub use sha1_asm::compress; } mod x86; use x86::compress as compress_inner; @@ -26,12 +24,15 @@ cfg_if::cfg_if! { } } +const BLOCK_SIZE: usize = ::BlockSize::USIZE; + /// SHA-1 compression function #[cfg_attr(docsrs, doc(cfg(feature = "compress")))] -pub fn compress(state: &mut [u32; 5], blocks: &[GenericArray]) { +pub fn compress(state: &mut [u32; 5], blocks: &[Block]) { // SAFETY: GenericArray and [u8; 64] have // exactly the same memory layout #[allow(unsafe_code)] - let blocks: &[[u8; 64]] = unsafe { &*(blocks as *const _ as *const [[u8; 64]]) }; + let blocks: &[[u8; BLOCK_SIZE]] = + unsafe { &*(blocks as *const _ as *const [[u8; BLOCK_SIZE]]) }; compress_inner(state, blocks); } diff --git a/sha1/src/compress/soft.rs b/sha1/src/compress/soft.rs index 19366fb13..f4777e7cc 100644 --- a/sha1/src/compress/soft.rs +++ b/sha1/src/compress/soft.rs @@ -1,7 +1,9 @@ #![allow(clippy::many_single_char_names)] -use crate::consts::{BLOCK_LEN, K0, K1, K2, K3}; +use super::BLOCK_SIZE; use core::convert::TryInto; +const K: [u32; 4] = [0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6]; + #[inline(always)] fn add(a: [u32; 4], b: [u32; 4]) -> [u32; 4] { [ @@ -47,16 +49,11 @@ fn sha1_first_half(abcd: [u32; 4], msg: [u32; 4]) -> [u32; 4] { } fn sha1_digest_round_x4(abcd: [u32; 4], work: [u32; 4], i: i8) -> [u32; 4] { - const K0V: [u32; 4] = [K0, K0, K0, K0]; - const K1V: [u32; 4] = [K1, K1, K1, K1]; - const K2V: [u32; 4] = [K2, K2, K2, K2]; - const K3V: [u32; 4] = [K3, K3, K3, K3]; - match i { - 0 => sha1rnds4c(abcd, add(work, K0V)), - 1 => sha1rnds4p(abcd, add(work, K1V)), - 2 => sha1rnds4m(abcd, add(work, K2V)), - 3 => sha1rnds4p(abcd, add(work, K3V)), + 0 => sha1rnds4c(abcd, add(work, [K[0]; 4])), + 1 => sha1rnds4p(abcd, add(work, [K[1]; 4])), + 2 => sha1rnds4m(abcd, add(work, [K[2]; 4])), + 3 => sha1rnds4p(abcd, add(work, [K[3]; 4])), _ => unreachable!("unknown icosaround index"), } } @@ -247,8 +244,8 @@ fn sha1_digest_block_u32(state: &mut [u32; 5], block: &[u32; 16]) { state[4] = state[4].wrapping_add(e); } -pub fn compress(state: &mut [u32; 5], blocks: &[[u8; 64]]) { - let mut block_u32 = [0u32; BLOCK_LEN]; +pub fn compress(state: &mut [u32; 5], blocks: &[[u8; BLOCK_SIZE]]) { + let mut block_u32 = [0u32; BLOCK_SIZE / 4]; // since LLVM can't properly use aliasing yet it will make // unnecessary state stores without this copy let mut state_cpy = *state; diff --git a/sha1/src/consts.rs b/sha1/src/consts.rs deleted file mode 100644 index c227df3a9..000000000 --- a/sha1/src/consts.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![allow(clippy::unreadable_literal, dead_code)] - -pub const STATE_LEN: usize = 5; - -pub const BLOCK_LEN: usize = 16; - -pub const K0: u32 = 0x5A827999u32; -pub const K1: u32 = 0x6ED9EBA1u32; -pub const K2: u32 = 0x8F1BBCDCu32; -pub const K3: u32 = 0xCA62C1D6u32; - -pub const H: [u32; STATE_LEN] = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]; diff --git a/sha1/src/lib.rs b/sha1/src/lib.rs index e1c8ac4a0..134108e77 100644 --- a/sha1/src/lib.rs +++ b/sha1/src/lib.rs @@ -36,81 +36,105 @@ #![no_std] #![cfg_attr(docsrs, feature(doc_cfg))] #![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_root_url = "https://docs.rs/sha-1/0.10.0" )] -#![deny(unsafe_code)] #![warn(missing_docs, rust_2018_idioms)] -#[cfg(feature = "std")] -extern crate std; +pub use digest::{self, Digest}; + +use core::{fmt, slice::from_ref}; +use digest::{ + block_buffer::Eager, + core_api::{ + AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore, + OutputSizeUser, Reset, UpdateCore, + }, + generic_array::typenum::{Unsigned, U20, U64}, + HashMarker, Output, +}; mod compress; -mod consts; #[cfg(feature = "compress")] -pub use crate::compress::compress; +pub use compress::compress; #[cfg(not(feature = "compress"))] -use crate::compress::compress; -use crate::consts::{H, STATE_LEN}; -use block_buffer::BlockBuffer; -use digest::consts::{U20, U64}; -pub use digest::{self, Digest}; -use digest::{BlockInput, FixedOutputDirty, Reset, Update}; +use compress::compress; + +const STATE_LEN: usize = 5; -/// Structure representing the state of a SHA-1 computation +/// Core SHA-1 hasher state. #[derive(Clone)] -pub struct Sha1 { +pub struct Sha1Core { h: [u32; STATE_LEN], - len: u64, - buffer: BlockBuffer, + block_len: u64, } -impl Default for Sha1 { - fn default() -> Self { - Sha1 { - h: H, - len: 0u64, - buffer: Default::default(), - } - } -} +impl HashMarker for Sha1Core {} -impl BlockInput for Sha1 { +impl BlockSizeUser for Sha1Core { type BlockSize = U64; } -impl Update for Sha1 { - fn update(&mut self, input: impl AsRef<[u8]>) { - let input = input.as_ref(); - // Assumes that `length_bits<<3` will not overflow - self.len += input.len() as u64; - let state = &mut self.h; - self.buffer.input_blocks(input, |d| compress(state, d)); - } +impl BufferKindUser for Sha1Core { + type BufferKind = Eager; } -impl FixedOutputDirty for Sha1 { +impl OutputSizeUser for Sha1Core { type OutputSize = U20; +} + +impl UpdateCore for Sha1Core { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + self.block_len += blocks.len() as u64; + compress(&mut self.h, blocks); + } +} - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - let s = &mut self.h; - let l = self.len << 3; - self.buffer - .len64_padding_be(l, |d| compress(s, core::slice::from_ref(d))); - for (chunk, v) in out.chunks_exact_mut(4).zip(self.h.iter()) { +impl FixedOutputCore for Sha1Core { + #[inline] + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + let bs = Self::BlockSize::U64; + let bit_len = 8 * (buffer.get_pos() as u64 + bs * self.block_len); + + let mut h = self.h; + buffer.len64_padding_be(bit_len, |b| compress(&mut h, from_ref(b))); + for (chunk, v) in out.chunks_exact_mut(4).zip(h.iter()) { chunk.copy_from_slice(&v.to_be_bytes()); } } } -impl Reset for Sha1 { +impl Default for Sha1Core { + #[inline] + fn default() -> Self { + Self { + h: [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0], + block_len: 0, + } + } +} + +impl Reset for Sha1Core { + #[inline] fn reset(&mut self) { - self.h = H; - self.len = 0; - self.buffer.reset(); + *self = Default::default(); + } +} + +impl AlgorithmName for Sha1Core { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Sha1") + } +} + +impl fmt::Debug for Sha1Core { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Sha1Core { ... }") } } -opaque_debug::implement!(Sha1); -digest::impl_write!(Sha1); +/// SHA-1 hasher state. +pub type Sha1 = CoreWrapper; diff --git a/sha1/tests/data/sha1.blb b/sha1/tests/data/sha1.blb index 13ae2df26..e8dc49163 100644 Binary files a/sha1/tests/data/sha1.blb and b/sha1/tests/data/sha1.blb differ diff --git a/sha2/CHANGELOG.md b/sha2/CHANGELOG.md index 433465d0b..3738c63a4 100644 --- a/sha2/CHANGELOG.md +++ b/sha2/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## 0.10.0 (2021-11-22) +### Changed +- Update to `digest` v0.10 ([#217]) + +[#217]: https://github.com/RustCrypto/hashes/pull/217 + ## 0.9.8 (2021-09-09) ### Fixed - Bug in the AVX2 backend ([#314]) diff --git a/sha2/Cargo.toml b/sha2/Cargo.toml index cf17feb8e..5a9984032 100644 --- a/sha2/Cargo.toml +++ b/sha2/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sha2" -version = "0.9.8" +version = "0.10.0" # Also update html_root_url in lib.rs when bumping this description = """ Pure Rust implementation of the SHA-2 hash function family including SHA-224, SHA-256, SHA-384, and SHA-512. @@ -15,9 +15,7 @@ keywords = ["crypto", "sha2", "hash", "digest"] categories = ["cryptography", "no-std"] [dependencies] -digest = "0.9" -block-buffer = "0.9" -opaque-debug = "0.3" +digest = "0.10" cfg-if = "1.0" sha2-asm = { version = "0.6.1", optional = true } @@ -25,7 +23,7 @@ sha2-asm = { version = "0.6.1", optional = true } cpufeatures = "0.2" [dev-dependencies] -digest = { version = "0.9", features = ["dev"] } +digest = { version = "0.10", features = ["dev"] } hex-literal = "0.2" [features] diff --git a/sha2/examples/sha256sum.rs b/sha2/examples/sha256sum.rs deleted file mode 100644 index 31ee97929..000000000 --- a/sha2/examples/sha256sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use sha2::{Digest, Sha256}; -use std::env; -use std::fs; -use std::io::{self, Read}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = D::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/sha2/examples/sha512sum.rs b/sha2/examples/sha512sum.rs deleted file mode 100644 index 9d4785acd..000000000 --- a/sha2/examples/sha512sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use sha2::{Digest, Sha512}; -use std::env; -use std::fs; -use std::io::{self, Read}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = D::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/sha2/src/lib.rs b/sha2/src/lib.rs index 1927067e1..9e2e43627 100644 --- a/sha2/src/lib.rs +++ b/sha2/src/lib.rs @@ -55,22 +55,186 @@ #![no_std] #![cfg_attr(docsrs, feature(doc_cfg))] #![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_root_url = "https://docs.rs/sha2/0.10.0" )] #![warn(missing_docs, rust_2018_idioms)] -#[cfg(feature = "std")] -extern crate std; +pub use digest::{self, Digest}; + +use core::{fmt, mem::size_of, slice::from_ref}; +use digest::{ + block_buffer::Eager, + core_api::{ + AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore, + OutputSizeUser, Reset, UpdateCore, + }, + generic_array::{ + typenum::{Unsigned, U128, U28, U32, U48, U64}, + GenericArray, + }, + HashMarker, Output, +}; mod consts; mod sha256; mod sha512; -pub use digest::{self, Digest}; #[cfg(feature = "compress")] pub use sha256::compress256; -pub use sha256::{Sha224, Sha256}; #[cfg(feature = "compress")] pub use sha512::compress512; -pub use sha512::{Sha384, Sha512, Sha512Trunc224, Sha512Trunc256}; + +macro_rules! implement { + ( + $name:ident, $full_name:ident, $init:expr, $block_size:ty, $out_size:ty, + $compress:expr, $word:ty, $dword:ty, $alg_name:expr, + ) => { + #[doc = "Core "] + #[doc = $alg_name] + #[doc = " hasher state."] + #[derive(Clone)] + pub struct $name { + state: [$word; 8], + block_len: $dword, + } + + impl HashMarker for $name {} + + impl BlockSizeUser for $name { + type BlockSize = $block_size; + } + + impl BufferKindUser for $name { + type BufferKind = Eager; + } + + impl OutputSizeUser for $name { + type OutputSize = $out_size; + } + + impl UpdateCore for $name { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + self.block_len += blocks.len() as $dword; + $compress(&mut self.state, blocks); + } + } + + impl FixedOutputCore for $name { + #[inline] + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + let bs = Self::BlockSize::U64 as $dword; + let bit_len = 8 * (buffer.get_pos() as $dword + bs * self.block_len); + let pad = bit_len.to_be_bytes(); + let s = &mut self.state; + buffer.digest_pad(0x80, &pad, |b| $compress(s, from_ref(b))); + let n = size_of::<$word>(); + for (chunk, v) in out.chunks_mut(n).zip(s.iter()) { + chunk.copy_from_slice(&v.to_be_bytes()[..chunk.len()]); + } + } + } + + impl Default for $name { + #[inline] + fn default() -> Self { + Self { + state: $init, + block_len: 0, + } + } + } + + impl Reset for $name { + #[inline] + fn reset(&mut self) { + *self = Default::default(); + } + } + + impl AlgorithmName for $name { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(stringify!($full_name)) + } + } + + impl fmt::Debug for $name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(concat!(stringify!($name), " { ... }")) + } + } + + #[doc = $alg_name] + #[doc = " hasher state."] + pub type $full_name = CoreWrapper<$name>; + }; +} + +implement!( + Sha224Core, + Sha224, + consts::H224, + U64, + U28, + sha256::compress256, + u32, + u64, + "SHA-224", +); +implement!( + Sha256Core, + Sha256, + consts::H256, + U64, + U32, + sha256::compress256, + u32, + u64, + "SHA-256", +); +implement!( + Sha512Trunc224Core, + Sha512Trunc224, + consts::H512_TRUNC_224, + U128, + U28, + sha512::compress512, + u64, + u128, + "SHA-512/224", +); +implement!( + Sha512Trunc256Core, + Sha512Trunc256, + consts::H512_TRUNC_256, + U128, + U32, + sha512::compress512, + u64, + u128, + "SHA-512/256", +); +implement!( + Sha384Core, + Sha384, + consts::H384, + U128, + U48, + sha512::compress512, + u64, + u128, + "SHA-384", +); +implement!( + Sha512Core, + Sha512, + consts::H512, + U128, + U64, + sha512::compress512, + u64, + u128, + "SHA-512", +); diff --git a/sha2/src/sha256.rs b/sha2/src/sha256.rs index 5e5909657..5ee19f6f7 100644 --- a/sha2/src/sha256.rs +++ b/sha2/src/sha256.rs @@ -1,142 +1,4 @@ -//! SHA-256 -use crate::consts::{H224, H256, STATE_LEN}; -use block_buffer::BlockBuffer; -use core::slice::from_ref; -use digest::consts::{U28, U32, U64}; -use digest::generic_array::GenericArray; -use digest::{BlockInput, FixedOutputDirty, Reset, Update}; - -type BlockSize = U64; - -/// Structure that keeps state of the Sha-256 operation and -/// contains the logic necessary to perform the final calculations. -#[derive(Clone)] -struct Engine256 { - len: u64, - buffer: BlockBuffer, - state: [u32; 8], -} - -impl Engine256 { - fn new(h: &[u32; STATE_LEN]) -> Engine256 { - Engine256 { - len: 0, - buffer: Default::default(), - state: *h, - } - } - - fn update(&mut self, input: &[u8]) { - // Assumes that input.len() can be converted to u64 without overflow - self.len += (input.len() as u64) << 3; - let s = &mut self.state; - self.buffer.input_blocks(input, |b| compress256(s, b)); - } - - fn finish(&mut self) { - let s = &mut self.state; - let l = self.len; - self.buffer - .len64_padding_be(l, |b| compress256(s, from_ref(b))); - } - - fn reset(&mut self, h: &[u32; STATE_LEN]) { - self.len = 0; - self.buffer.reset(); - self.state = *h; - } -} - -/// The SHA-256 hash algorithm with the SHA-256 initial hash value. -#[derive(Clone)] -pub struct Sha256 { - engine: Engine256, -} - -impl Default for Sha256 { - fn default() -> Self { - Sha256 { - engine: Engine256::new(&H256), - } - } -} - -impl BlockInput for Sha256 { - type BlockSize = BlockSize; -} - -impl Update for Sha256 { - fn update(&mut self, input: impl AsRef<[u8]>) { - self.engine.update(input.as_ref()); - } -} - -impl FixedOutputDirty for Sha256 { - type OutputSize = U32; - - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - self.engine.finish(); - let s = self.engine.state; - for (chunk, v) in out.chunks_exact_mut(4).zip(s.iter()) { - chunk.copy_from_slice(&v.to_be_bytes()); - } - } -} - -impl Reset for Sha256 { - fn reset(&mut self) { - self.engine.reset(&H256); - } -} - -/// The SHA-256 hash algorithm with the SHA-224 initial hash value. The result -/// is truncated to 224 bits. -#[derive(Clone)] -pub struct Sha224 { - engine: Engine256, -} - -impl Default for Sha224 { - fn default() -> Self { - Sha224 { - engine: Engine256::new(&H224), - } - } -} - -impl BlockInput for Sha224 { - type BlockSize = BlockSize; -} - -impl Update for Sha224 { - fn update(&mut self, input: impl AsRef<[u8]>) { - self.engine.update(input.as_ref()); - } -} - -impl FixedOutputDirty for Sha224 { - type OutputSize = U28; - - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - self.engine.finish(); - let s = &self.engine.state[..7]; - for (chunk, v) in out.chunks_exact_mut(4).zip(s.iter()) { - chunk.copy_from_slice(&v.to_be_bytes()); - } - } -} - -impl Reset for Sha224 { - fn reset(&mut self) { - self.engine.reset(&H224); - } -} - -opaque_debug::implement!(Sha224); -opaque_debug::implement!(Sha256); - -digest::impl_write!(Sha224); -digest::impl_write!(Sha256); +use super::{GenericArray, U64}; cfg_if::cfg_if! { if #[cfg(feature = "force-soft")] { @@ -147,9 +9,7 @@ cfg_if::cfg_if! { mod soft; #[cfg(feature = "asm")] mod soft { - pub(crate) fn compress(state: &mut [u32; 8], blocks: &[[u8; 64]]) { - sha2_asm::compress256(state, blocks); - } + pub(crate) use sha2_asm::compress256 as compress; } mod x86; use x86::compress; @@ -171,7 +31,7 @@ cfg_if::cfg_if! { pub fn compress256(state: &mut [u32; 8], blocks: &[GenericArray]) { // SAFETY: GenericArray and [u8; 64] have // exactly the same memory layout - #[allow(unsafe_code)] - let blocks: &[[u8; 64]] = unsafe { &*(blocks as *const _ as *const [[u8; 64]]) }; + let p = blocks.as_ptr() as *const [u8; 64]; + let blocks = unsafe { core::slice::from_raw_parts(p, blocks.len()) }; compress(state, blocks) } diff --git a/sha2/src/sha512.rs b/sha2/src/sha512.rs index 22f141e43..c52927ba3 100644 --- a/sha2/src/sha512.rs +++ b/sha2/src/sha512.rs @@ -1,231 +1,4 @@ -//! SHA-512 -use crate::consts::{H384, H512, H512_TRUNC_224, H512_TRUNC_256, STATE_LEN}; -use block_buffer::BlockBuffer; -use core::slice::from_ref; -use digest::consts::{U128, U28, U32, U48, U64}; -use digest::generic_array::GenericArray; -use digest::{BlockInput, FixedOutputDirty, Reset, Update}; - -type BlockSize = U128; - -/// Structure that keeps state of the Sha-512 operation and -/// contains the logic necessary to perform the final calculations. -#[derive(Clone)] -struct Engine512 { - len: u128, - buffer: BlockBuffer, - state: [u64; 8], -} - -impl Engine512 { - fn new(h: &[u64; STATE_LEN]) -> Engine512 { - Engine512 { - len: 0, - buffer: Default::default(), - state: *h, - } - } - - fn update(&mut self, input: &[u8]) { - self.len += (input.len() as u128) << 3; - let s = &mut self.state; - self.buffer.input_blocks(input, |b| compress512(s, b)); - } - - fn finish(&mut self) { - let s = &mut self.state; - self.buffer - .len128_padding_be(self.len, |d| compress512(s, from_ref(d))); - } - - fn reset(&mut self, h: &[u64; STATE_LEN]) { - self.len = 0; - self.buffer.reset(); - self.state = *h; - } -} - -/// The SHA-512 hash algorithm with the SHA-512 initial hash value. -#[derive(Clone)] -pub struct Sha512 { - engine: Engine512, -} - -impl Default for Sha512 { - fn default() -> Self { - Sha512 { - engine: Engine512::new(&H512), - } - } -} - -impl BlockInput for Sha512 { - type BlockSize = BlockSize; -} - -impl Update for Sha512 { - fn update(&mut self, input: impl AsRef<[u8]>) { - self.engine.update(input.as_ref()); - } -} - -impl FixedOutputDirty for Sha512 { - type OutputSize = U64; - - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - self.engine.finish(); - let s = self.engine.state; - for (chunk, v) in out.chunks_exact_mut(8).zip(s.iter()) { - chunk.copy_from_slice(&v.to_be_bytes()); - } - } -} - -impl Reset for Sha512 { - fn reset(&mut self) { - self.engine.reset(&H512); - } -} - -/// The SHA-512 hash algorithm with the SHA-384 initial hash value. The result -/// is truncated to 384 bits. -#[derive(Clone)] -pub struct Sha384 { - engine: Engine512, -} - -impl Default for Sha384 { - fn default() -> Self { - Sha384 { - engine: Engine512::new(&H384), - } - } -} - -impl BlockInput for Sha384 { - type BlockSize = BlockSize; -} - -impl Update for Sha384 { - fn update(&mut self, input: impl AsRef<[u8]>) { - self.engine.update(input.as_ref()); - } -} - -impl FixedOutputDirty for Sha384 { - type OutputSize = U48; - - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - self.engine.finish(); - let s = &self.engine.state[..6]; - for (chunk, v) in out.chunks_exact_mut(8).zip(s.iter()) { - chunk.copy_from_slice(&v.to_be_bytes()); - } - } -} - -impl Reset for Sha384 { - fn reset(&mut self) { - self.engine.reset(&H384); - } -} - -/// The SHA-512 hash algorithm with the SHA-512/256 initial hash value. The -/// result is truncated to 256 bits. -#[derive(Clone)] -pub struct Sha512Trunc256 { - engine: Engine512, -} - -impl Default for Sha512Trunc256 { - fn default() -> Self { - Sha512Trunc256 { - engine: Engine512::new(&H512_TRUNC_256), - } - } -} - -impl BlockInput for Sha512Trunc256 { - type BlockSize = BlockSize; -} - -impl Update for Sha512Trunc256 { - fn update(&mut self, input: impl AsRef<[u8]>) { - self.engine.update(input.as_ref()); - } -} - -impl FixedOutputDirty for Sha512Trunc256 { - type OutputSize = U32; - - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - self.engine.finish(); - let s = &self.engine.state[..4]; - for (chunk, v) in out.chunks_exact_mut(8).zip(s.iter()) { - chunk.copy_from_slice(&v.to_be_bytes()); - } - } -} - -impl Reset for Sha512Trunc256 { - fn reset(&mut self) { - self.engine.reset(&H512_TRUNC_256); - } -} - -/// The SHA-512 hash algorithm with the SHA-512/224 initial hash value. -/// The result is truncated to 224 bits. -#[derive(Clone)] -pub struct Sha512Trunc224 { - engine: Engine512, -} - -impl Default for Sha512Trunc224 { - fn default() -> Self { - Sha512Trunc224 { - engine: Engine512::new(&H512_TRUNC_224), - } - } -} - -impl BlockInput for Sha512Trunc224 { - type BlockSize = BlockSize; -} - -impl Update for Sha512Trunc224 { - fn update(&mut self, input: impl AsRef<[u8]>) { - self.engine.update(input.as_ref()); - } -} - -impl FixedOutputDirty for Sha512Trunc224 { - type OutputSize = U28; - - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - self.engine.finish(); - let s = &self.engine.state; - for (chunk, v) in out.chunks_exact_mut(8).zip(s[..3].iter()) { - chunk.copy_from_slice(&v.to_be_bytes()); - } - out[24..28].copy_from_slice(&s[3].to_be_bytes()[..4]); - } -} - -impl Reset for Sha512Trunc224 { - fn reset(&mut self) { - self.engine.reset(&H512_TRUNC_224); - } -} - -opaque_debug::implement!(Sha384); -opaque_debug::implement!(Sha512); -opaque_debug::implement!(Sha512Trunc224); -opaque_debug::implement!(Sha512Trunc256); - -digest::impl_write!(Sha384); -digest::impl_write!(Sha512); -digest::impl_write!(Sha512Trunc224); -digest::impl_write!(Sha512Trunc256); +use super::{GenericArray, U128}; cfg_if::cfg_if! { if #[cfg(feature = "force-soft")] { @@ -254,9 +27,9 @@ cfg_if::cfg_if! { /// functionality of SHA-512. #[cfg_attr(docsrs, doc(cfg(feature = "compress")))] pub fn compress512(state: &mut [u64; 8], blocks: &[GenericArray]) { - // SAFETY: GenericArray and [u8; 128] have + // SAFETY: GenericArray and [u8; 64] have // exactly the same memory layout - #[allow(unsafe_code)] - let blocks: &[[u8; 128]] = unsafe { &*(blocks as *const _ as *const [[u8; 128]]) }; + let p = blocks.as_ptr() as *const [u8; 128]; + let blocks = unsafe { core::slice::from_raw_parts(p, blocks.len()) }; compress(state, blocks) } diff --git a/sha2/tests/data/sha224.blb b/sha2/tests/data/sha224.blb index 50759c294..69327048a 100644 Binary files a/sha2/tests/data/sha224.blb and b/sha2/tests/data/sha224.blb differ diff --git a/sha2/tests/data/sha256.blb b/sha2/tests/data/sha256.blb index 2096fd4ec..389a12578 100644 Binary files a/sha2/tests/data/sha256.blb and b/sha2/tests/data/sha256.blb differ diff --git a/sha2/tests/data/sha384.blb b/sha2/tests/data/sha384.blb index 7e9062497..74a151f42 100644 Binary files a/sha2/tests/data/sha384.blb and b/sha2/tests/data/sha384.blb differ diff --git a/sha2/tests/data/sha512.blb b/sha2/tests/data/sha512.blb index b073a77cb..bb2ec390c 100644 Binary files a/sha2/tests/data/sha512.blb and b/sha2/tests/data/sha512.blb differ diff --git a/sha2/tests/data/sha512_224.blb b/sha2/tests/data/sha512_224.blb index 4d2ef87ff..3c3ab8fac 100644 Binary files a/sha2/tests/data/sha512_224.blb and b/sha2/tests/data/sha512_224.blb differ diff --git a/sha2/tests/data/sha512_256.blb b/sha2/tests/data/sha512_256.blb index 5346c9494..acd380aa0 100644 Binary files a/sha2/tests/data/sha512_256.blb and b/sha2/tests/data/sha512_256.blb differ diff --git a/sha2/tests/lib.rs b/sha2/tests/lib.rs index fe120455b..6e8db6975 100644 --- a/sha2/tests/lib.rs +++ b/sha2/tests/lib.rs @@ -36,7 +36,7 @@ fn sha512_avx2_bug() { 2a3e943072f30afa45f2bf57ccd386f29b76dbcdb3a861224ca0b77bc3f55c7a d3880a49c0c9c166eedf7f209c41b380896886155acb8f6c7c07044343a3e692 "); - let res = sha2::Sha512::digest(&msg); + let res = sha2::Sha512::digest(&msg[..]); assert_eq!(res[..], expected[..]); } diff --git a/sha3/CHANGELOG.md b/sha3/CHANGELOG.md index 6d2b6b7bc..fee3168a8 100644 --- a/sha3/CHANGELOG.md +++ b/sha3/CHANGELOG.md @@ -5,6 +5,11 @@ 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). +## 0.10.0 (2021-11-22) +### Changed +- Update to `digest` v0.10 ([#217]) + +[#217]: https://github.com/RustCrypto/hashes/pull/217 ## 0.9.1 (2020-06-28) ### Changed diff --git a/sha3/Cargo.toml b/sha3/Cargo.toml index 57824552d..faae04c30 100644 --- a/sha3/Cargo.toml +++ b/sha3/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sha3" -version = "0.9.1" +version = "0.10.0" # Also update html_root_url in lib.rs when bumping this description = "SHA-3 (Keccak) hash function" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -12,13 +12,11 @@ keywords = ["crypto", "sha3", "keccak", "hash", "digest"] categories = ["cryptography", "no-std"] [dependencies] -digest = "0.9" -block-buffer = { version = "0.9", features = ["block-padding"] } -opaque-debug = "0.3" +digest = "0.10" keccak = "0.1" [dev-dependencies] -digest = { version = "0.9", features = ["dev"] } +digest = { version = "0.10", features = ["dev"] } hex-literal = "0.2" [features] diff --git a/sha3/examples/sha3_256sum.rs b/sha3/examples/sha3_256sum.rs deleted file mode 100644 index bc9da2e08..000000000 --- a/sha3/examples/sha3_256sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use sha3::{Digest, Sha3_256}; -use std::env; -use std::fs; -use std::io::{self, Read}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = D::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/sha3/examples/sha3_512sum.rs b/sha3/examples/sha3_512sum.rs deleted file mode 100644 index 1bfbe3b89..000000000 --- a/sha3/examples/sha3_512sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use sha3::{Digest, Sha3_512}; -use std::env; -use std::fs; -use std::io::{self, Read}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = D::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/sha3/src/lib.rs b/sha3/src/lib.rs index 831762955..b6dcee0b2 100644 --- a/sha3/src/lib.rs +++ b/sha3/src/lib.rs @@ -58,106 +58,72 @@ #![no_std] #![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_root_url = "https://docs.rs/sha3/0.10.0" )] #![deny(unsafe_code)] #![warn(missing_docs, rust_2018_idioms)] -#[cfg(feature = "std")] -extern crate std; - pub use digest::{self, Digest}; -use block_buffer::BlockBuffer; -use digest::consts::{U104, U136, U144, U168, U200, U28, U32, U48, U64, U72}; -use digest::generic_array::typenum::Unsigned; -use digest::{BlockInput, ExtendableOutputDirty, FixedOutputDirty, Reset, Update}; +use core::fmt; +use digest::{ + block_buffer::Eager, + consts::{U104, U136, U144, U168, U200, U28, U32, U48, U64, U72}, + core_api::{ + AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, + ExtendableOutputCore, FixedOutputCore, OutputSizeUser, Reset, UpdateCore, XofReaderCore, + XofReaderCoreWrapper, + }, + HashMarker, Output, +}; -mod paddings; #[macro_use] mod macros; -mod reader; mod state; -pub use crate::reader::Sha3XofReader; use crate::state::Sha3State; -sha3_impl!( - Keccak224, - U28, - U144, - paddings::Keccak, - "Keccak-224 hash function." -); -sha3_impl!( - Keccak256, - U32, - U136, - paddings::Keccak, - "Keccak-256 hash function." -); -sha3_impl!( - Keccak384, - U48, - U104, - paddings::Keccak, - "Keccak-384 hash function." -); -sha3_impl!( - Keccak512, - U64, - U72, - paddings::Keccak, - "Keccak-512 hash function." -); +// Paddings +const KECCAK: u8 = 0x01; +const SHA3: u8 = 0x06; +const SHAKE: u8 = 0x1f; -sha3_impl!( +impl_sha3!(Keccak224Core, Keccak224, U28, U144, KECCAK, "Keccak-224"); +impl_sha3!(Keccak256Core, Keccak256, U32, U136, KECCAK, "Keccak-256"); +impl_sha3!(Keccak384Core, Keccak384, U48, U104, KECCAK, "Keccak-384"); +impl_sha3!(Keccak512Core, Keccak512, U64, U72, KECCAK, "Keccak-512"); + +impl_sha3!( + Keccak256FullCore, Keccak256Full, U200, U136, - paddings::Keccak, - "SHA-3 variant used in CryptoNight." + KECCAK, + "SHA-3 CryptoNight variant", ); -sha3_impl!( - Sha3_224, - U28, - U144, - paddings::Sha3, - "SHA-3-224 hash function." -); -sha3_impl!( - Sha3_256, - U32, - U136, - paddings::Sha3, - "SHA-3-256 hash function." -); -sha3_impl!( - Sha3_384, - U48, - U104, - paddings::Sha3, - "SHA-3-384 hash function." -); -sha3_impl!( - Sha3_512, - U64, - U72, - paddings::Sha3, - "SHA-3-512 hash function." -); +impl_sha3!(Sha3_224Core, Sha3_224, U28, U144, SHA3, "SHA-3-224"); +impl_sha3!(Sha3_256Core, Sha3_256, U32, U136, SHA3, "SHA-3-256"); +impl_sha3!(Sha3_384Core, Sha3_384, U48, U104, SHA3, "SHA-3-384"); +impl_sha3!(Sha3_512Core, Sha3_512, U64, U72, SHA3, "SHA-3-512"); -shake_impl!( +impl_shake!( + Shake128Core, Shake128, + Shake128ReaderCore, + Shake128Reader, U168, - paddings::Shake, - "SHAKE128 extendable output (XOF) hash function" + SHAKE, + "SHAKE128", ); -shake_impl!( +impl_shake!( + Shake256Core, Shake256, + Shake256ReaderCore, + Shake256Reader, U136, - paddings::Shake, - "SHAKE256 extendable output (XOF) hash function" + SHAKE, + "SHAKE256", ); diff --git a/sha3/src/macros.rs b/sha3/src/macros.rs index b690124c8..1ec96367b 100644 --- a/sha3/src/macros.rs +++ b/sha3/src/macros.rs @@ -1,49 +1,50 @@ -macro_rules! impl_state { - ($state:ident, $rate:ident, $padding:ty, $doc:expr) => { +macro_rules! impl_sha3 { + ( + $name:ident, $full_name:ident, $output_size:ident, + $rate:ident, $pad:expr, $alg_name:expr $(,)? + ) => { + #[doc = "Core "] + #[doc = $alg_name] + #[doc = " hasher state."] + #[derive(Clone)] #[allow(non_camel_case_types)] - #[derive(Clone, Default)] - #[doc=$doc] - pub struct $state { + pub struct $name { state: Sha3State, - buffer: BlockBuffer<$rate>, } - impl $state { - fn absorb(&mut self, input: &[u8]) { - let s = &mut self.state; - self.buffer.input_block(input, |b| s.absorb_block(b)); - } + impl HashMarker for $name {} - fn apply_padding(&mut self) { - let buf = self - .buffer - .pad_with::<$padding>() - .expect("we never use input_lazy"); - self.state.absorb_block(buf); - } + impl BlockSizeUser for $name { + type BlockSize = $rate; } - }; -} -macro_rules! sha3_impl { - ($state:ident, $output_size:ident, $rate:ident, $padding:ty, $doc:expr) => { - impl_state!($state, $rate, $padding, $doc); + impl BufferKindUser for $name { + type BufferKind = Eager; + } - impl BlockInput for $state { - type BlockSize = $rate; + impl OutputSizeUser for $name { + type OutputSize = $output_size; } - impl Update for $state { - fn update(&mut self, input: impl AsRef<[u8]>) { - self.absorb(input.as_ref()) + impl UpdateCore for $name { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + for block in blocks { + self.state.absorb_block(block) + } } } - impl FixedOutputDirty for $state { - type OutputSize = $output_size; + impl FixedOutputCore for $name { + #[inline] + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + let pos = buffer.get_pos(); + let block = buffer.pad_with_zeros(); + block[pos] = $pad; + let n = block.len(); + block[n - 1] |= 0x80; - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - self.apply_padding(); + self.state.absorb_block(block); let n = out.len(); self.state.as_bytes(|state| { @@ -52,46 +53,151 @@ macro_rules! sha3_impl { } } - impl Reset for $state { + impl Default for $name { + #[inline] + fn default() -> Self { + Self { + state: Default::default(), + } + } + } + + impl Reset for $name { + #[inline] fn reset(&mut self) { - self.state = Default::default(); - self.buffer.reset(); + *self = Default::default(); } } - opaque_debug::implement!($state); - digest::impl_write!($state); + impl AlgorithmName for $name { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(stringify!($full_name)) + } + } + + impl fmt::Debug for $name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(concat!(stringify!($name), " { ... }")) + } + } + + #[doc = $alg_name] + #[doc = " hasher state."] + pub type $full_name = CoreWrapper<$name>; }; } -macro_rules! shake_impl { - ($state:ident, $rate:ident, $padding:ty, $doc:expr) => { - impl_state!($state, $rate, $padding, $doc); +macro_rules! impl_shake { + ( + $name:ident, $full_name:ident, $reader:ident, $reader_full:ident, + $rate:ident, $pad:expr, $alg_name:expr, + ) => { + #[doc = "Core "] + #[doc = $alg_name] + #[doc = " hasher state."] + #[derive(Clone)] + #[allow(non_camel_case_types)] + pub struct $name { + state: Sha3State, + } + + impl HashMarker for $name {} + + impl BlockSizeUser for $name { + type BlockSize = $rate; + } + + impl BufferKindUser for $name { + type BufferKind = Eager; + } - impl Update for $state { - fn update(&mut self, input: impl AsRef<[u8]>) { - self.absorb(input.as_ref()) + impl UpdateCore for $name { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + for block in blocks { + self.state.absorb_block(block) + } } } - impl ExtendableOutputDirty for $state { - type Reader = Sha3XofReader; + impl ExtendableOutputCore for $name { + type ReaderCore = $reader; + + #[inline] + fn finalize_xof_core(&mut self, buffer: &mut Buffer) -> Self::ReaderCore { + let pos = buffer.get_pos(); + let block = buffer.pad_with_zeros(); + block[pos] = $pad; + let n = block.len(); + block[n - 1] |= 0x80; + + self.state.absorb_block(block); + $reader { + state: self.state.clone(), + } + } + } - fn finalize_xof_dirty(&mut self) -> Sha3XofReader { - self.apply_padding(); - let r = $rate::to_usize(); - Sha3XofReader::new(self.state.clone(), r) + impl Default for $name { + #[inline] + fn default() -> Self { + Self { + state: Default::default(), + } } } - impl Reset for $state { + impl Reset for $name { + #[inline] fn reset(&mut self) { - self.state = Default::default(); - self.buffer.reset(); + *self = Default::default(); + } + } + + impl AlgorithmName for $name { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(stringify!($full_name)) + } + } + + impl fmt::Debug for $name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(concat!(stringify!($name), " { ... }")) + } + } + + #[doc = "Core "] + #[doc = $alg_name] + #[doc = " reader state."] + #[derive(Clone)] + #[allow(non_camel_case_types)] + pub struct $reader { + state: Sha3State, + } + + impl BlockSizeUser for $reader { + type BlockSize = $rate; + } + + impl XofReaderCore for $reader { + #[inline] + fn read_block(&mut self) -> Block { + let mut block = Block::::default(); + let n = block.len(); + self.state.as_bytes(|state| { + block.copy_from_slice(&state[..n]); + }); + self.state.apply_f(); + block } } - opaque_debug::implement!($state); - digest::impl_write!($state); + #[doc = $alg_name] + #[doc = " hasher state."] + pub type $full_name = CoreWrapper<$name>; + + #[doc = $alg_name] + #[doc = " reader state."] + pub type $reader_full = XofReaderCoreWrapper<$name>; }; } diff --git a/sha3/src/paddings.rs b/sha3/src/paddings.rs deleted file mode 100644 index d11c87f89..000000000 --- a/sha3/src/paddings.rs +++ /dev/null @@ -1,33 +0,0 @@ -use block_buffer::block_padding::{PadError, Padding, UnpadError}; - -macro_rules! impl_padding { - ($name:ident, $pad:expr) => { - // it does not work with empty enum as it required to have Default impl - // for it for some unclear reason. - #[derive(Copy, Clone, Default)] - pub struct $name; - - impl Padding for $name { - #[inline(always)] - fn pad_block(block: &mut [u8], pos: usize) -> Result<(), PadError> { - if pos >= block.len() { - return Err(PadError); - } - block[pos] = $pad; - block[pos + 1..].iter_mut().for_each(|b| *b = 0); - let n = block.len(); - block[n - 1] |= 0x80; - Ok(()) - } - - #[inline(always)] - fn unpad(_data: &[u8]) -> Result<&[u8], UnpadError> { - unimplemented!(); - } - } - }; -} - -impl_padding!(Keccak, 0x01); -impl_padding!(Sha3, 0x06); -impl_padding!(Shake, 0x1f); diff --git a/sha3/src/reader.rs b/sha3/src/reader.rs deleted file mode 100644 index fbb2d716e..000000000 --- a/sha3/src/reader.rs +++ /dev/null @@ -1,66 +0,0 @@ -use crate::state::Sha3State; -use digest::XofReader; -#[cfg(feature = "std")] -use std::io; - -/// Reader state for extracting extendable output. -pub struct Sha3XofReader { - state: Sha3State, - rate: usize, - pos: usize, -} - -impl Sha3XofReader { - pub(crate) fn new(state: Sha3State, rate: usize) -> Self { - Sha3XofReader { - state, - rate, - pos: 0, - } - } -} - -impl XofReader for Sha3XofReader { - fn read(&mut self, mut buffer: &mut [u8]) { - let rem = self.rate - self.pos; - let n = buffer.len(); - if n >= rem { - let (l, r) = { buffer }.split_at_mut(rem); - buffer = r; - self.state.as_bytes(|state| { - l.copy_from_slice(&state[self.pos..self.rate]); - }); - self.state.apply_f(); - } else { - self.state.as_bytes(|state| { - buffer.copy_from_slice(&state[self.pos..self.pos + n]); - }); - self.pos += n; - return; - } - - while buffer.len() >= self.rate { - let (l, r) = { buffer }.split_at_mut(self.rate); - buffer = r; - - self.state.as_bytes(|state| { - l.copy_from_slice(&state[..self.rate]); - }); - self.state.apply_f(); - } - - let n = buffer.len(); - self.pos = n; - self.state.as_bytes(|state| { - buffer.copy_from_slice(&state[..n]); - }); - } -} - -#[cfg(feature = "std")] -impl io::Read for Sha3XofReader { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - ::read(self, buf); - Ok(buf.len()) - } -} diff --git a/sha3/tests/data/keccak_224.blb b/sha3/tests/data/keccak_224.blb index 97d8c4975..393d0aceb 100644 Binary files a/sha3/tests/data/keccak_224.blb and b/sha3/tests/data/keccak_224.blb differ diff --git a/sha3/tests/data/keccak_256.blb b/sha3/tests/data/keccak_256.blb index 6558741ba..d964e2094 100644 Binary files a/sha3/tests/data/keccak_256.blb and b/sha3/tests/data/keccak_256.blb differ diff --git a/sha3/tests/data/keccak_256_full.blb b/sha3/tests/data/keccak_256_full.blb index 733224241..71af3f234 100644 Binary files a/sha3/tests/data/keccak_256_full.blb and b/sha3/tests/data/keccak_256_full.blb differ diff --git a/sha3/tests/data/keccak_384.blb b/sha3/tests/data/keccak_384.blb index c21ab269b..250942944 100644 Binary files a/sha3/tests/data/keccak_384.blb and b/sha3/tests/data/keccak_384.blb differ diff --git a/sha3/tests/data/keccak_512.blb b/sha3/tests/data/keccak_512.blb index 687719d26..a9e47e077 100644 Binary files a/sha3/tests/data/keccak_512.blb and b/sha3/tests/data/keccak_512.blb differ diff --git a/sha3/tests/data/sha3_224.blb b/sha3/tests/data/sha3_224.blb index 40d4412ea..510e160c4 100644 Binary files a/sha3/tests/data/sha3_224.blb and b/sha3/tests/data/sha3_224.blb differ diff --git a/sha3/tests/data/sha3_256.blb b/sha3/tests/data/sha3_256.blb index 3634b8af8..00fe6fcd9 100644 Binary files a/sha3/tests/data/sha3_256.blb and b/sha3/tests/data/sha3_256.blb differ diff --git a/sha3/tests/data/sha3_384.blb b/sha3/tests/data/sha3_384.blb index b5006290d..802759adf 100644 Binary files a/sha3/tests/data/sha3_384.blb and b/sha3/tests/data/sha3_384.blb differ diff --git a/sha3/tests/data/sha3_512.blb b/sha3/tests/data/sha3_512.blb index b64785eff..b02800c0f 100644 Binary files a/sha3/tests/data/sha3_512.blb and b/sha3/tests/data/sha3_512.blb differ diff --git a/sha3/tests/data/shake128.blb b/sha3/tests/data/shake128.blb index 70177c7db..58fb20814 100644 Binary files a/sha3/tests/data/shake128.blb and b/sha3/tests/data/shake128.blb differ diff --git a/sha3/tests/data/shake256.blb b/sha3/tests/data/shake256.blb index e2ee0bb64..c5340e26a 100644 Binary files a/sha3/tests/data/shake256.blb and b/sha3/tests/data/shake256.blb differ diff --git a/shabal/CHANGELOG.md b/shabal/CHANGELOG.md index d44eb49f9..02c4ef9bc 100644 --- a/shabal/CHANGELOG.md +++ b/shabal/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## 0.4.0 (2021-11-22) +### Changed +- Update to `digest` v0.10 ([#217]) + +[#217]: https://github.com/RustCrypto/hashes/pull/217 + ## 0.3.0 (2020-06-12) ### Changed - Bump `opaque-debug` to v0.3.0 ([#168]) diff --git a/shabal/Cargo.toml b/shabal/Cargo.toml index a83f02704..e0f0edb9d 100644 --- a/shabal/Cargo.toml +++ b/shabal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shabal" -version = "0.3.0" +version = "0.4.0" # Also update html_root_url in lib.rs when bumping this description = "Shabal hash functions" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -12,12 +12,10 @@ keywords = ["crypto", "shabal", "hash", "digest"] categories = ["cryptography", "no-std"] [dependencies] -digest = "0.9" -block-buffer = { version = "0.9", features = ["block-padding"] } -opaque-debug = "0.3" +digest = "0.10" [dev-dependencies] -digest = { version = "0.9", features = ["dev"] } +digest = { version = "0.10", features = ["dev"] } hex-literal = "0.2" [features] diff --git a/shabal/examples/shabal256sum.rs b/shabal/examples/shabal256sum.rs deleted file mode 100644 index 5a5186183..000000000 --- a/shabal/examples/shabal256sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use shabal::{Digest, Shabal256}; -use std::env; -use std::fs; -use std::io::{self, Read}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = D::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/shabal/examples/shabal512sum.rs b/shabal/examples/shabal512sum.rs deleted file mode 100644 index b045f6581..000000000 --- a/shabal/examples/shabal512sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use shabal::{Digest, Shabal512}; -use std::env; -use std::fs; -use std::io::{self, Read}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = D::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/shabal/src/consts.rs b/shabal/src/consts.rs index 27fddcdbe..73150fb45 100644 --- a/shabal/src/consts.rs +++ b/shabal/src/consts.rs @@ -1,264 +1,106 @@ -pub const A_INIT_512: [u32; 12] = [ - 0x2072_8DFD, - 0x46C0_BD53, - 0xE782_B699, - 0x5530_4632, - 0x71B4_EF90, - 0x0EA9_E82C, - 0xDBB9_30F1, - 0xFAD0_6B8B, - 0xBE0C_AE40, - 0x8BD1_4410, - 0x76D2_ADAC, - 0x28AC_AB7F, -]; +//! Shabal initialization constants. -pub const B_INIT_512: [u32; 16] = [ - 0xC109_9CB7, - 0x07B3_85F3, - 0xE744_2C26, - 0xCC8A_D640, - 0xEB6F_56C7, - 0x1EA8_1AA9, - 0x73B9_D314, - 0x1DE8_5D08, - 0x4891_0A5A, - 0x893B_22DB, - 0xC5A0_DF44, - 0xBBC4_324E, - 0x72D2_F240, - 0x7594_1D99, - 0x6D8B_DE82, - 0xA1A7_502B, -]; +#[rustfmt::skip] +pub(crate) const INIT_192: ([u32; 12], [u32; 16], [u32; 16]) = ( + [ + 0xFD74_9ED4, 0xB798_E530, 0x3390_4B6F, 0x46BD_A85E, + 0x0769_34B4, 0x454B_4058, 0x77F7_4527, 0xFB4C_F465, + 0x6293_1DA9, 0xE778_C8DB, 0x22B3_998E, 0xAC15_CFB9, + ], + [ + 0x58BC_BAC4, 0xEC47_A08E, 0xAEE9_33B2, 0xDFCB_C824, + 0xA794_4804, 0xBF65_BDB0, 0x5A9D_4502, 0x5997_9AF7, + 0xC5CE_A54E, 0x4B6B_8150, 0x16E7_1909, 0x7D63_2319, + 0x9305_73A0, 0xF34C_63D1, 0xCAF9_14B4, 0xFDD6_612C, + ], + [ + 0x6155_0878, 0x89EF_2B75, 0xA166_0C46, 0x7EF3_855B, + 0x7297_B58C, 0x1BC6_7793, 0x7FB1_C723, 0xB66F_C640, + 0x1A48_B71C, 0xF097_6D17, 0x088C_E80A, 0xA454_EDF3, + 0x1C09_6BF4, 0xAC76_224B, 0x5215_781C, 0xCD5D_2669, + ], +); -pub const C_INIT_512: [u32; 16] = [ - 0xD9BF_68D1, - 0x58BA_D750, - 0x5602_8CB2, - 0x8134_F359, - 0xB5D4_69D8, - 0x941A_8CC2, - 0x418B_2A6E, - 0x0405_2780, - 0x7F07_D787, - 0x5194_358F, - 0x3C60_D665, - 0xBE97_D79A, - 0x950C_3434, - 0xAED9_A06D, - 0x2537_DC8D, - 0x7CDB_5969, -]; +#[rustfmt::skip] +pub(crate) const INIT_224: ([u32; 12], [u32; 16], [u32; 16]) = ( + [ + 0xA520_1467, 0xA9B8_D94A, 0xD4CE_D997, 0x6837_9D7B, + 0xA7FC_73BA, 0xF1A2_546B, 0x6067_82BF, 0xE0BC_FD0F, + 0x2F25_374E, 0x069A_149F, 0x5E2D_FF25, 0xFAEC_F061, + ], + [ + 0xEC99_05D8, 0xF218_50CF, 0xC0A7_46C8, 0x21DA_D498, + 0x3515_6EEB, 0x088C_97F2, 0x2630_3E40, 0x8A2D_4FB5, + 0xFEEE_44B6, 0x8A1E_9573, 0x7B81_111A, 0xCBC1_39F0, + 0xA351_3861, 0x1D2C_362E, 0x918C_580E, 0xB58E_1B9C, + ], + [ + 0xE4B5_73A1, 0x4C1A_0880, 0x1E90_7C51, 0x0480_7EFD, + 0x3AD8_CDE5, 0x16B2_1302, 0x0251_2C53, 0x2204_CB18, + 0x9940_5F2D, 0xE5B6_48A1, 0x70AB_1D43, 0xA10C_25C2, + 0x16F1_AC05, 0x38BB_EB56, 0x9B01_DC60, 0xB109_6D83, + ], +); -pub const A_INIT_384: [u32; 12] = [ - 0xC8FC_A331, - 0xE55C_504E, - 0x003E_BF26, - 0xBB6B_8D83, - 0x7B04_48C1, - 0x41B8_2789, - 0x0A7C_9601, - 0x8D65_9CFF, - 0xB6E2_673E, - 0xCA54_C77B, - 0x1460_FD7E, - 0x3FCB_8F2D, -]; +#[rustfmt::skip] +pub(crate) const INIT_256: ([u32; 12], [u32; 16], [u32; 16]) = ( + [ + 0x52F8_4552, 0xE54B_7999, 0x2D8E_E3EC, 0xB964_5191, + 0xE007_8B86, 0xBB7C_44C9, 0xD2B5_C1CA, 0xB0D2_EB8C, + 0x14CE_5A45, 0x22AF_50DC, 0xEFFD_BC6B, 0xEB21_B74A, + ], + [ + 0xB555_C6EE, 0x3E71_0596, 0xA72A_652F, 0x9301_515F, + 0xDA28_C1FA, 0x696F_D868, 0x9CB6_BF72, 0x0AFE_4002, + 0xA6E0_3615, 0x5138_C1D4, 0xBE21_6306, 0xB38B_8890, + 0x3EA8_B96B, 0x3299_ACE4, 0x3092_4DD4, 0x55CB_34A5, + ], + [ + 0xB405_F031, 0xC423_3EBA, 0xB373_3979, 0xC0DD_9D55, + 0xC51C_28AE, 0xA327_B8E1, 0x56C5_6167, 0xED61_4433, + 0x88B5_9D60, 0x60E2_CEBA, 0x758B_4B8B, 0x83E8_2A7F, + 0xBC96_8828, 0xE6E0_0BF7, 0xBA83_9E55, 0x9B49_1C60, + ], +); -pub const B_INIT_384: [u32; 16] = [ - 0x5272_91FC, - 0x2A16_455F, - 0x78E6_27E5, - 0x944F_169F, - 0x1CA6_F016, - 0xA854_EA25, - 0x8DB9_8ABE, - 0xF2C6_2641, - 0x3011_7DCB, - 0xCF5C_4309, - 0x9371_1A25, - 0xF9F6_71B8, - 0xB01D_2116, - 0x333F_4B89, - 0xB285_D165, - 0x8682_9B36, -]; +#[rustfmt::skip] +pub(crate) const INIT_384: ([u32; 12], [u32; 16], [u32; 16]) = ( + [ + 0xC8FC_A331, 0xE55C_504E, 0x003E_BF26, 0xBB6B_8D83, + 0x7B04_48C1, 0x41B8_2789, 0x0A7C_9601, 0x8D65_9CFF, + 0xB6E2_673E, 0xCA54_C77B, 0x1460_FD7E, 0x3FCB_8F2D, + ], + [ + 0x5272_91FC, 0x2A16_455F, 0x78E6_27E5, 0x944F_169F, + 0x1CA6_F016, 0xA854_EA25, 0x8DB9_8ABE, 0xF2C6_2641, + 0x3011_7DCB, 0xCF5C_4309, 0x9371_1A25, 0xF9F6_71B8, + 0xB01D_2116, 0x333F_4B89, 0xB285_D165, 0x8682_9B36, + ], + [ + 0xF764_B11A, 0x7617_2146, 0xCEF6_934D, 0xC6D2_8399, + 0xFE09_5F61, 0x5E60_18B4, 0x5048_ECF5, 0x5135_3261, + 0x6E6E_36DC, 0x6313_0DAD, 0xA9C6_9BD6, 0x1E90_EA0C, + 0x7C35_073B, 0x28D9_5E6D, 0xAA34_0E0D, 0xCB3D_EE70, + ], +); -pub const C_INIT_384: [u32; 16] = [ - 0xF764_B11A, - 0x7617_2146, - 0xCEF6_934D, - 0xC6D2_8399, - 0xFE09_5F61, - 0x5E60_18B4, - 0x5048_ECF5, - 0x5135_3261, - 0x6E6E_36DC, - 0x6313_0DAD, - 0xA9C6_9BD6, - 0x1E90_EA0C, - 0x7C35_073B, - 0x28D9_5E6D, - 0xAA34_0E0D, - 0xCB3D_EE70, -]; - -pub const A_INIT_256: [u32; 12] = [ - 0x52F8_4552, - 0xE54B_7999, - 0x2D8E_E3EC, - 0xB964_5191, - 0xE007_8B86, - 0xBB7C_44C9, - 0xD2B5_C1CA, - 0xB0D2_EB8C, - 0x14CE_5A45, - 0x22AF_50DC, - 0xEFFD_BC6B, - 0xEB21_B74A, -]; - -pub const B_INIT_256: [u32; 16] = [ - 0xB555_C6EE, - 0x3E71_0596, - 0xA72A_652F, - 0x9301_515F, - 0xDA28_C1FA, - 0x696F_D868, - 0x9CB6_BF72, - 0x0AFE_4002, - 0xA6E0_3615, - 0x5138_C1D4, - 0xBE21_6306, - 0xB38B_8890, - 0x3EA8_B96B, - 0x3299_ACE4, - 0x3092_4DD4, - 0x55CB_34A5, -]; - -pub const C_INIT_256: [u32; 16] = [ - 0xB405_F031, - 0xC423_3EBA, - 0xB373_3979, - 0xC0DD_9D55, - 0xC51C_28AE, - 0xA327_B8E1, - 0x56C5_6167, - 0xED61_4433, - 0x88B5_9D60, - 0x60E2_CEBA, - 0x758B_4B8B, - 0x83E8_2A7F, - 0xBC96_8828, - 0xE6E0_0BF7, - 0xBA83_9E55, - 0x9B49_1C60, -]; - -pub const A_INIT_224: [u32; 12] = [ - 0xA520_1467, - 0xA9B8_D94A, - 0xD4CE_D997, - 0x6837_9D7B, - 0xA7FC_73BA, - 0xF1A2_546B, - 0x6067_82BF, - 0xE0BC_FD0F, - 0x2F25_374E, - 0x069A_149F, - 0x5E2D_FF25, - 0xFAEC_F061, -]; - -pub const B_INIT_224: [u32; 16] = [ - 0xEC99_05D8, - 0xF218_50CF, - 0xC0A7_46C8, - 0x21DA_D498, - 0x3515_6EEB, - 0x088C_97F2, - 0x2630_3E40, - 0x8A2D_4FB5, - 0xFEEE_44B6, - 0x8A1E_9573, - 0x7B81_111A, - 0xCBC1_39F0, - 0xA351_3861, - 0x1D2C_362E, - 0x918C_580E, - 0xB58E_1B9C, -]; - -pub const C_INIT_224: [u32; 16] = [ - 0xE4B5_73A1, - 0x4C1A_0880, - 0x1E90_7C51, - 0x0480_7EFD, - 0x3AD8_CDE5, - 0x16B2_1302, - 0x0251_2C53, - 0x2204_CB18, - 0x9940_5F2D, - 0xE5B6_48A1, - 0x70AB_1D43, - 0xA10C_25C2, - 0x16F1_AC05, - 0x38BB_EB56, - 0x9B01_DC60, - 0xB109_6D83, -]; - -pub const A_INIT_192: [u32; 12] = [ - 0xFD74_9ED4, - 0xB798_E530, - 0x3390_4B6F, - 0x46BD_A85E, - 0x0769_34B4, - 0x454B_4058, - 0x77F7_4527, - 0xFB4C_F465, - 0x6293_1DA9, - 0xE778_C8DB, - 0x22B3_998E, - 0xAC15_CFB9, -]; - -pub const B_INIT_192: [u32; 16] = [ - 0x58BC_BAC4, - 0xEC47_A08E, - 0xAEE9_33B2, - 0xDFCB_C824, - 0xA794_4804, - 0xBF65_BDB0, - 0x5A9D_4502, - 0x5997_9AF7, - 0xC5CE_A54E, - 0x4B6B_8150, - 0x16E7_1909, - 0x7D63_2319, - 0x9305_73A0, - 0xF34C_63D1, - 0xCAF9_14B4, - 0xFDD6_612C, -]; - -pub const C_INIT_192: [u32; 16] = [ - 0x6155_0878, - 0x89EF_2B75, - 0xA166_0C46, - 0x7EF3_855B, - 0x7297_B58C, - 0x1BC6_7793, - 0x7FB1_C723, - 0xB66F_C640, - 0x1A48_B71C, - 0xF097_6D17, - 0x088C_E80A, - 0xA454_EDF3, - 0x1C09_6BF4, - 0xAC76_224B, - 0x5215_781C, - 0xCD5D_2669, -]; +#[rustfmt::skip] +pub(crate) const INIT_512: ([u32; 12], [u32; 16], [u32; 16]) = ( + [ + 0x2072_8DFD, 0x46C0_BD53, 0xE782_B699, 0x5530_4632, + 0x71B4_EF90, 0x0EA9_E82C, 0xDBB9_30F1, 0xFAD0_6B8B, + 0xBE0C_AE40, 0x8BD1_4410, 0x76D2_ADAC, 0x28AC_AB7F, + ], + [ + 0xC109_9CB7, 0x07B3_85F3, 0xE744_2C26, 0xCC8A_D640, + 0xEB6F_56C7, 0x1EA8_1AA9, 0x73B9_D314, 0x1DE8_5D08, + 0x4891_0A5A, 0x893B_22DB, 0xC5A0_DF44, 0xBBC4_324E, + 0x72D2_F240, 0x7594_1D99, 0x6D8B_DE82, 0xA1A7_502B, + ], + [ + 0xD9BF_68D1, 0x58BA_D750, 0x5602_8CB2, 0x8134_F359, + 0xB5D4_69D8, 0x941A_8CC2, 0x418B_2A6E, 0x0405_2780, + 0x7F07_D787, 0x5194_358F, 0x3C60_D665, 0xBE97_D79A, + 0x950C_3434, 0xAED9_A06D, 0x2537_DC8D, 0x7CDB_5969, + ], +); diff --git a/shabal/src/lib.rs b/shabal/src/lib.rs index ecb5e96e1..8cb3ca23a 100644 --- a/shabal/src/lib.rs +++ b/shabal/src/lib.rs @@ -26,7 +26,9 @@ //! // acquire hash digest in the form of GenericArray, //! // which in this case is equivalent to [u8; 32] //! let result = hasher.finalize(); -//! assert_eq!(result[..], hex!("d945dee21ffca23ac232763aa9cac6c15805f144db9d6c97395437e01c8595a8")); +//! assert_eq!(result[..], hex!(" +//! d945dee21ffca23ac232763aa9cac6c15805f144db9d6c97395437e01c8595a8 +//! ")[..]); //! ``` //! //! Also see [RustCrypto/hashes][2] readme. @@ -36,8 +38,9 @@ #![no_std] #![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_root_url = "https://docs.rs/shabal/0.4.0" )] #![deny(unsafe_code)] #![warn(missing_docs, rust_2018_idioms)] @@ -46,7 +49,107 @@ extern crate std; mod consts; -mod shabal; +mod state; -pub use crate::shabal::{Shabal192, Shabal224, Shabal256, Shabal384, Shabal512}; pub use digest::{self, Digest}; + +use core::fmt; +use digest::{ + block_buffer::Eager, + consts::{U24, U28, U32, U48, U64}, + core_api::{ + AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore, + OutputSizeUser, Reset, UpdateCore, + }, + generic_array::typenum::Unsigned, + HashMarker, Output, +}; +use state::{compress, compress_final, BlockSize, EngineState}; + +macro_rules! impl_core { + ($name:ident, $full_name:ident, $init:expr, $out_size:ty, $alg_name:expr) => { + #[doc = "Core "] + #[doc = $alg_name] + #[doc = " hasher state."] + #[derive(Clone)] + pub struct $name { + state: EngineState, + } + + impl HashMarker for $name {} + + impl BlockSizeUser for $name { + type BlockSize = BlockSize; + } + + impl BufferKindUser for $name { + type BufferKind = Eager; + } + + impl OutputSizeUser for $name { + type OutputSize = $out_size; + } + + impl UpdateCore for $name { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + for block in blocks { + compress(&mut self.state, block) + } + } + } + + impl FixedOutputCore for $name { + #[inline] + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + let pos = buffer.get_pos(); + let block = buffer.pad_with_zeros(); + block[pos] = 0x80; + compress_final(&mut self.state, &block); + let n = 16 - <$out_size>::USIZE / 4; + let b = &self.state.get_b()[n..]; + for (chunk, v) in out.chunks_exact_mut(4).zip(b.iter()) { + chunk.copy_from_slice(&v.to_le_bytes()); + } + } + } + + impl Default for $name { + #[inline] + fn default() -> Self { + Self { + state: EngineState::new($init), + } + } + } + + impl Reset for $name { + #[inline] + fn reset(&mut self) { + *self = Default::default(); + } + } + + impl AlgorithmName for $name { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(stringify!($full_name)) + } + } + + impl fmt::Debug for $name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(concat!(stringify!($name), " { ... }")) + } + } + + #[doc = $alg_name] + #[doc = " hasher state."] + pub type $full_name = CoreWrapper<$name>; + }; +} + +impl_core!(Shabal192Core, Shabal192, consts::INIT_192, U24, "Shabal192"); +impl_core!(Shabal224Core, Shabal224, consts::INIT_224, U28, "Shabal224"); +impl_core!(Shabal256Core, Shabal256, consts::INIT_256, U32, "Shabal256"); +impl_core!(Shabal384Core, Shabal384, consts::INIT_384, U48, "Shabal384"); +impl_core!(Shabal512Core, Shabal512, consts::INIT_512, U64, "Shabal512"); diff --git a/shabal/src/shabal.rs b/shabal/src/shabal.rs deleted file mode 100644 index 09d3879be..000000000 --- a/shabal/src/shabal.rs +++ /dev/null @@ -1,513 +0,0 @@ -//! Shabal -use block_buffer::block_padding::Iso7816; -use block_buffer::BlockBuffer; -use core::convert::TryInto; -use digest::{ - consts::{U24, U28, U32, U48, U64}, - generic_array::GenericArray, -}; -use digest::{BlockInput, FixedOutputDirty, Reset, Update}; - -use crate::consts::{ - A_INIT_192, A_INIT_224, A_INIT_256, A_INIT_384, A_INIT_512, B_INIT_192, B_INIT_224, B_INIT_256, - B_INIT_384, B_INIT_512, C_INIT_192, C_INIT_224, C_INIT_256, C_INIT_384, C_INIT_512, -}; - -type BlockSize = U64; -type Block = GenericArray; - -/// A structure that represents that state of a digest computation for the -/// Shabal family of digest functions -#[derive(Clone)] -struct EngineState { - a: [u32; 12], - b: [u32; 16], - c: [u32; 16], - whigh: u32, - wlow: u32, -} - -impl EngineState { - fn new(a: &[u32; 12], b: &[u32; 16], c: &[u32; 16]) -> Self { - Self { - a: *a, - b: *b, - c: *c, - wlow: 1, - whigh: 0, - } - } - - fn process_block(&mut self, block: &Block) { - #[allow(unsafe_code)] - let block = unsafe { &*(block.as_ptr() as *const [u8; 64]) }; - compress(self, block); - } - - fn process_final_block(&mut self, block: &Block) { - #[allow(unsafe_code)] - let block = unsafe { &*(block.as_ptr() as *const [u8; 64]) }; - compress_final(self, block); - } - - #[inline] - fn add_m(&mut self, m: &[u32; 16]) { - for (b, m) in self.b.iter_mut().zip(m) { - *b = b.wrapping_add(*m); - } - } - - #[inline] - fn sub_m(&mut self, m: &[u32; 16]) { - for (c, m) in self.c.iter_mut().zip(m) { - *c = c.wrapping_sub(*m); - } - } - - #[inline] - fn inc_w(&mut self) { - self.wlow = self.wlow.wrapping_add(1); - if self.wlow == 0 { - self.whigh = self.whigh.wrapping_add(1); - } - } - - #[inline] - fn xor_w(&mut self) { - self.a[0] ^= self.wlow; - self.a[1] ^= self.whigh; - } - - #[inline] - fn perm(&mut self, m: &[u32; 16]) { - for b in self.b.iter_mut() { - *b = b.wrapping_shl(17) | b.wrapping_shr(15); - } - self.perm_blocks(m); - - let a = &mut self.a; - let c = &self.c; - a[0] = a[0] - .wrapping_add(c[11]) - .wrapping_add(c[15]) - .wrapping_add(c[3]); - a[1] = a[1] - .wrapping_add(c[12]) - .wrapping_add(c[0]) - .wrapping_add(c[4]); - a[2] = a[2] - .wrapping_add(c[13]) - .wrapping_add(c[1]) - .wrapping_add(c[5]); - a[3] = a[3] - .wrapping_add(c[14]) - .wrapping_add(c[2]) - .wrapping_add(c[6]); - a[4] = a[4] - .wrapping_add(c[15]) - .wrapping_add(c[3]) - .wrapping_add(c[7]); - a[5] = a[5] - .wrapping_add(c[0]) - .wrapping_add(c[4]) - .wrapping_add(c[8]); - a[6] = a[6] - .wrapping_add(c[1]) - .wrapping_add(c[5]) - .wrapping_add(c[9]); - a[7] = a[7] - .wrapping_add(c[2]) - .wrapping_add(c[6]) - .wrapping_add(c[10]); - a[8] = a[8] - .wrapping_add(c[3]) - .wrapping_add(c[7]) - .wrapping_add(c[11]); - a[9] = a[9] - .wrapping_add(c[4]) - .wrapping_add(c[8]) - .wrapping_add(c[12]); - a[10] = a[10] - .wrapping_add(c[5]) - .wrapping_add(c[9]) - .wrapping_add(c[13]); - a[11] = a[11] - .wrapping_add(c[6]) - .wrapping_add(c[10]) - .wrapping_add(c[14]); - } - - #[inline] - #[allow(clippy::too_many_arguments)] - fn perm_elt( - &mut self, - xa0: usize, - xa1: usize, - xb0: usize, - xb1: usize, - xb2: usize, - xb3: usize, - xc0: usize, - xm: u32, - ) { - let a = &mut self.a; - let b = &mut self.b; - let xc = self.c[xc0]; - - a[xa0] = (a[xa0] - ^ ((a[xa1].wrapping_shl(15u32) | a[xa1].wrapping_shr(17u32)).wrapping_mul(5u32)) - ^ xc) - .wrapping_mul(3u32) - ^ b[xb1] - ^ (b[xb2] & !b[xb3]) - ^ xm; - b[xb0] = !((b[xb0].wrapping_shl(1) | b[xb0].wrapping_shr(31)) ^ a[xa0]); - } - - #[inline] - fn perm_blocks(&mut self, m: &[u32; 16]) { - self.perm_elt(0, 11, 0, 13, 9, 6, 8, m[0]); - self.perm_elt(1, 0, 1, 14, 10, 7, 7, m[1]); - self.perm_elt(2, 1, 2, 15, 11, 8, 6, m[2]); - self.perm_elt(3, 2, 3, 0, 12, 9, 5, m[3]); - self.perm_elt(4, 3, 4, 1, 13, 10, 4, m[4]); - self.perm_elt(5, 4, 5, 2, 14, 11, 3, m[5]); - self.perm_elt(6, 5, 6, 3, 15, 12, 2, m[6]); - self.perm_elt(7, 6, 7, 4, 0, 13, 1, m[7]); - self.perm_elt(8, 7, 8, 5, 1, 14, 0, m[8]); - self.perm_elt(9, 8, 9, 6, 2, 15, 15, m[9]); - self.perm_elt(10, 9, 10, 7, 3, 0, 14, m[10]); - self.perm_elt(11, 10, 11, 8, 4, 1, 13, m[11]); - self.perm_elt(0, 11, 12, 9, 5, 2, 12, m[12]); - self.perm_elt(1, 0, 13, 10, 6, 3, 11, m[13]); - self.perm_elt(2, 1, 14, 11, 7, 4, 10, m[14]); - self.perm_elt(3, 2, 15, 12, 8, 5, 9, m[15]); - self.perm_elt(4, 3, 0, 13, 9, 6, 8, m[0]); - self.perm_elt(5, 4, 1, 14, 10, 7, 7, m[1]); - self.perm_elt(6, 5, 2, 15, 11, 8, 6, m[2]); - self.perm_elt(7, 6, 3, 0, 12, 9, 5, m[3]); - self.perm_elt(8, 7, 4, 1, 13, 10, 4, m[4]); - self.perm_elt(9, 8, 5, 2, 14, 11, 3, m[5]); - self.perm_elt(10, 9, 6, 3, 15, 12, 2, m[6]); - self.perm_elt(11, 10, 7, 4, 0, 13, 1, m[7]); - self.perm_elt(0, 11, 8, 5, 1, 14, 0, m[8]); - self.perm_elt(1, 0, 9, 6, 2, 15, 15, m[9]); - self.perm_elt(2, 1, 10, 7, 3, 0, 14, m[10]); - self.perm_elt(3, 2, 11, 8, 4, 1, 13, m[11]); - self.perm_elt(4, 3, 12, 9, 5, 2, 12, m[12]); - self.perm_elt(5, 4, 13, 10, 6, 3, 11, m[13]); - self.perm_elt(6, 5, 14, 11, 7, 4, 10, m[14]); - self.perm_elt(7, 6, 15, 12, 8, 5, 9, m[15]); - self.perm_elt(8, 7, 0, 13, 9, 6, 8, m[0]); - self.perm_elt(9, 8, 1, 14, 10, 7, 7, m[1]); - self.perm_elt(10, 9, 2, 15, 11, 8, 6, m[2]); - self.perm_elt(11, 10, 3, 0, 12, 9, 5, m[3]); - self.perm_elt(0, 11, 4, 1, 13, 10, 4, m[4]); - self.perm_elt(1, 0, 5, 2, 14, 11, 3, m[5]); - self.perm_elt(2, 1, 6, 3, 15, 12, 2, m[6]); - self.perm_elt(3, 2, 7, 4, 0, 13, 1, m[7]); - self.perm_elt(4, 3, 8, 5, 1, 14, 0, m[8]); - self.perm_elt(5, 4, 9, 6, 2, 15, 15, m[9]); - self.perm_elt(6, 5, 10, 7, 3, 0, 14, m[10]); - self.perm_elt(7, 6, 11, 8, 4, 1, 13, m[11]); - self.perm_elt(8, 7, 12, 9, 5, 2, 12, m[12]); - self.perm_elt(9, 8, 13, 10, 6, 3, 11, m[13]); - self.perm_elt(10, 9, 14, 11, 7, 4, 10, m[14]); - self.perm_elt(11, 10, 15, 12, 8, 5, 9, m[15]); - } - - #[inline] - fn swap_b_c(&mut self) { - ::core::mem::swap(&mut self.b, &mut self.c); - } -} - -/// A structure that keeps track of the state of the Shabal operation and -/// contains the logic necessary to perform the final calculations. -#[derive(Clone)] -struct Engine256 { - buffer: BlockBuffer, - state: EngineState, -} - -impl Engine256 { - fn new(a: &[u32; 12], b: &[u32; 16], c: &[u32; 16]) -> Engine256 { - Engine256 { - buffer: Default::default(), - state: EngineState::new(a, b, c), - } - } - - fn input(&mut self, input: &[u8]) { - let s = &mut self.state; - self.buffer.input_block(input, |b| s.process_block(b)); - } - - fn finish(&mut self) { - let state = &mut self.state; - let block = self.buffer.pad_with::().unwrap(); - state.process_final_block(block); - } - - fn reset(&mut self, a: &[u32; 12], b: &[u32; 16], c: &[u32; 16]) { - self.state = EngineState::new(a, b, c); - self.buffer.reset(); - } -} - -/// The Shabal hash algorithm with the Shabal-512 initial hash value. -#[derive(Clone)] -pub struct Shabal512 { - engine: Engine256, -} - -impl Default for Shabal512 { - fn default() -> Self { - Self { - engine: Engine256::new(&A_INIT_512, &B_INIT_512, &C_INIT_512), - } - } -} - -impl BlockInput for Shabal512 { - type BlockSize = BlockSize; -} - -impl Update for Shabal512 { - fn update(&mut self, input: impl AsRef<[u8]>) { - self.engine.input(input.as_ref()); - } -} - -impl FixedOutputDirty for Shabal512 { - type OutputSize = U64; - - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - self.engine.finish(); - let b = &self.engine.state.b[0..16]; - for (chunk, v) in out.chunks_exact_mut(4).zip(b.iter()) { - chunk.copy_from_slice(&v.to_le_bytes()); - } - } -} - -impl Reset for Shabal512 { - fn reset(&mut self) { - self.engine.reset(&A_INIT_512, &B_INIT_512, &C_INIT_512); - } -} - -/// The Shabal hash algorithm with the Shabal-384 initial hash value. The result -/// is truncated to 384 bits. -#[derive(Clone)] -pub struct Shabal384 { - engine: Engine256, -} - -impl Default for Shabal384 { - fn default() -> Self { - Self { - engine: Engine256::new(&A_INIT_384, &B_INIT_384, &C_INIT_384), - } - } -} - -impl BlockInput for Shabal384 { - type BlockSize = BlockSize; -} - -impl Update for Shabal384 { - fn update(&mut self, input: impl AsRef<[u8]>) { - self.engine.input(input.as_ref()); - } -} - -impl FixedOutputDirty for Shabal384 { - type OutputSize = U48; - - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - self.engine.finish(); - let b = &self.engine.state.b[4..16]; - for (chunk, v) in out.chunks_exact_mut(4).zip(b.iter()) { - chunk.copy_from_slice(&v.to_le_bytes()); - } - } -} - -impl Reset for Shabal384 { - fn reset(&mut self) { - self.engine.reset(&A_INIT_384, &B_INIT_384, &C_INIT_384); - } -} - -/// The Shabal hash algorithm with the Shabal-256 initial hash value. The result -/// is truncated to 256 bits. -#[derive(Clone)] -pub struct Shabal256 { - engine: Engine256, -} - -impl Default for Shabal256 { - fn default() -> Self { - Self { - engine: Engine256::new(&A_INIT_256, &B_INIT_256, &C_INIT_256), - } - } -} - -impl BlockInput for Shabal256 { - type BlockSize = BlockSize; -} - -impl Update for Shabal256 { - fn update(&mut self, input: impl AsRef<[u8]>) { - self.engine.input(input.as_ref()); - } -} - -impl FixedOutputDirty for Shabal256 { - type OutputSize = U32; - - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - self.engine.finish(); - let b = &self.engine.state.b[8..16]; - for (chunk, v) in out.chunks_exact_mut(4).zip(b.iter()) { - chunk.copy_from_slice(&v.to_le_bytes()); - } - } -} - -impl Reset for Shabal256 { - fn reset(&mut self) { - self.engine.reset(&A_INIT_256, &B_INIT_256, &C_INIT_256); - } -} - -/// The Shabal hash algorithm with the Shabal-224 initial hash value. The result -/// is truncated to 224 bits. -#[derive(Clone)] -pub struct Shabal224 { - engine: Engine256, -} - -impl Default for Shabal224 { - fn default() -> Self { - Self { - engine: Engine256::new(&A_INIT_224, &B_INIT_224, &C_INIT_224), - } - } -} - -impl BlockInput for Shabal224 { - type BlockSize = BlockSize; -} - -impl Update for Shabal224 { - fn update(&mut self, input: impl AsRef<[u8]>) { - self.engine.input(input.as_ref()); - } -} - -impl FixedOutputDirty for Shabal224 { - type OutputSize = U28; - - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - self.engine.finish(); - let b = &self.engine.state.b[9..16]; - for (chunk, v) in out.chunks_exact_mut(4).zip(b.iter()) { - chunk.copy_from_slice(&v.to_le_bytes()); - } - } -} - -impl Reset for Shabal224 { - fn reset(&mut self) { - self.engine.reset(&A_INIT_224, &B_INIT_224, &C_INIT_224); - } -} - -/// The Shabal hash algorithm with the Shabal-192 initial hash value. The result -/// is truncated to 192 bits. -#[derive(Clone)] -pub struct Shabal192 { - engine: Engine256, -} - -impl Default for Shabal192 { - fn default() -> Self { - Self { - engine: Engine256::new(&A_INIT_192, &B_INIT_192, &C_INIT_192), - } - } -} - -impl BlockInput for Shabal192 { - type BlockSize = BlockSize; -} - -impl Update for Shabal192 { - fn update(&mut self, input: impl AsRef<[u8]>) { - self.engine.input(input.as_ref()); - } -} - -impl FixedOutputDirty for Shabal192 { - type OutputSize = U24; - - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - self.engine.finish(); - let b = &self.engine.state.b[10..16]; - for (chunk, v) in out.chunks_exact_mut(4).zip(b.iter()) { - chunk.copy_from_slice(&v.to_le_bytes()); - } - } -} - -impl Reset for Shabal192 { - fn reset(&mut self) { - self.engine.reset(&A_INIT_192, &B_INIT_192, &C_INIT_192); - } -} - -opaque_debug::implement!(Shabal512); -opaque_debug::implement!(Shabal384); -opaque_debug::implement!(Shabal256); -opaque_debug::implement!(Shabal224); -opaque_debug::implement!(Shabal192); - -digest::impl_write!(Shabal512); -digest::impl_write!(Shabal384); -digest::impl_write!(Shabal256); -digest::impl_write!(Shabal224); -digest::impl_write!(Shabal192); - -#[inline] -fn read_m(input: &[u8; 64]) -> [u32; 16] { - let mut m = [0u32; 16]; - for (o, chunk) in m.iter_mut().zip(input.chunks_exact(4)) { - *o = u32::from_le_bytes(chunk.try_into().unwrap()); - } - m -} - -fn compress(state: &mut EngineState, input: &[u8; 64]) { - let m = read_m(input); - state.add_m(&m); - state.xor_w(); - state.perm(&m); - state.sub_m(&m); - state.swap_b_c(); - state.inc_w(); -} - -fn compress_final(state: &mut EngineState, input: &[u8; 64]) { - let m = read_m(input); - state.add_m(&m); - state.xor_w(); - state.perm(&m); - for _ in 0..3 { - state.swap_b_c(); - state.xor_w(); - state.perm(&m); - } -} diff --git a/shabal/src/state.rs b/shabal/src/state.rs new file mode 100644 index 000000000..1d26a3fa8 --- /dev/null +++ b/shabal/src/state.rs @@ -0,0 +1,226 @@ +use core::{convert::TryInto, mem}; +use digest::{consts::U64, generic_array::GenericArray}; + +pub(crate) type BlockSize = U64; +pub(crate) type Block = GenericArray; + +/// Inner state of Shabal hash functions. +#[derive(Clone)] +pub(crate) struct EngineState { + a: [u32; 12], + b: [u32; 16], + c: [u32; 16], + whigh: u32, + wlow: u32, +} + +impl EngineState { + pub(crate) const fn new((a, b, c): ([u32; 12], [u32; 16], [u32; 16])) -> Self { + let (wlow, whigh) = (1, 0); + Self { + a, + b, + c, + wlow, + whigh, + } + } + + pub(crate) fn get_b(&self) -> &[u32; 16] { + &self.b + } + + fn add_m(&mut self, m: &[u32; 16]) { + for (b, m) in self.b.iter_mut().zip(m) { + *b = b.wrapping_add(*m); + } + } + + fn sub_m(&mut self, m: &[u32; 16]) { + for (c, m) in self.c.iter_mut().zip(m) { + *c = c.wrapping_sub(*m); + } + } + + fn inc_w(&mut self) { + self.wlow = self.wlow.wrapping_add(1); + if self.wlow == 0 { + self.whigh = self.whigh.wrapping_add(1); + } + } + + fn xor_w(&mut self) { + self.a[0] ^= self.wlow; + self.a[1] ^= self.whigh; + } + + fn perm(&mut self, m: &[u32; 16]) { + for b in self.b.iter_mut() { + *b = b.wrapping_shl(17) | b.wrapping_shr(15); + } + self.perm_blocks(m); + + let a = &mut self.a; + let c = &self.c; + a[0] = a[0] + .wrapping_add(c[11]) + .wrapping_add(c[15]) + .wrapping_add(c[3]); + a[1] = a[1] + .wrapping_add(c[12]) + .wrapping_add(c[0]) + .wrapping_add(c[4]); + a[2] = a[2] + .wrapping_add(c[13]) + .wrapping_add(c[1]) + .wrapping_add(c[5]); + a[3] = a[3] + .wrapping_add(c[14]) + .wrapping_add(c[2]) + .wrapping_add(c[6]); + a[4] = a[4] + .wrapping_add(c[15]) + .wrapping_add(c[3]) + .wrapping_add(c[7]); + a[5] = a[5] + .wrapping_add(c[0]) + .wrapping_add(c[4]) + .wrapping_add(c[8]); + a[6] = a[6] + .wrapping_add(c[1]) + .wrapping_add(c[5]) + .wrapping_add(c[9]); + a[7] = a[7] + .wrapping_add(c[2]) + .wrapping_add(c[6]) + .wrapping_add(c[10]); + a[8] = a[8] + .wrapping_add(c[3]) + .wrapping_add(c[7]) + .wrapping_add(c[11]); + a[9] = a[9] + .wrapping_add(c[4]) + .wrapping_add(c[8]) + .wrapping_add(c[12]); + a[10] = a[10] + .wrapping_add(c[5]) + .wrapping_add(c[9]) + .wrapping_add(c[13]); + a[11] = a[11] + .wrapping_add(c[6]) + .wrapping_add(c[10]) + .wrapping_add(c[14]); + } + + #[allow(clippy::too_many_arguments)] + fn perm_elt( + &mut self, + xa0: usize, + xa1: usize, + xb0: usize, + xb1: usize, + xb2: usize, + xb3: usize, + xc0: usize, + xm: u32, + ) { + let a = &mut self.a; + let b = &mut self.b; + let xc = self.c[xc0]; + + a[xa0] = (a[xa0] + ^ ((a[xa1].wrapping_shl(15u32) | a[xa1].wrapping_shr(17u32)).wrapping_mul(5u32)) + ^ xc) + .wrapping_mul(3u32) + ^ b[xb1] + ^ (b[xb2] & !b[xb3]) + ^ xm; + b[xb0] = !((b[xb0].wrapping_shl(1) | b[xb0].wrapping_shr(31)) ^ a[xa0]); + } + + fn perm_blocks(&mut self, m: &[u32; 16]) { + self.perm_elt(0, 11, 0, 13, 9, 6, 8, m[0]); + self.perm_elt(1, 0, 1, 14, 10, 7, 7, m[1]); + self.perm_elt(2, 1, 2, 15, 11, 8, 6, m[2]); + self.perm_elt(3, 2, 3, 0, 12, 9, 5, m[3]); + self.perm_elt(4, 3, 4, 1, 13, 10, 4, m[4]); + self.perm_elt(5, 4, 5, 2, 14, 11, 3, m[5]); + self.perm_elt(6, 5, 6, 3, 15, 12, 2, m[6]); + self.perm_elt(7, 6, 7, 4, 0, 13, 1, m[7]); + self.perm_elt(8, 7, 8, 5, 1, 14, 0, m[8]); + self.perm_elt(9, 8, 9, 6, 2, 15, 15, m[9]); + self.perm_elt(10, 9, 10, 7, 3, 0, 14, m[10]); + self.perm_elt(11, 10, 11, 8, 4, 1, 13, m[11]); + self.perm_elt(0, 11, 12, 9, 5, 2, 12, m[12]); + self.perm_elt(1, 0, 13, 10, 6, 3, 11, m[13]); + self.perm_elt(2, 1, 14, 11, 7, 4, 10, m[14]); + self.perm_elt(3, 2, 15, 12, 8, 5, 9, m[15]); + self.perm_elt(4, 3, 0, 13, 9, 6, 8, m[0]); + self.perm_elt(5, 4, 1, 14, 10, 7, 7, m[1]); + self.perm_elt(6, 5, 2, 15, 11, 8, 6, m[2]); + self.perm_elt(7, 6, 3, 0, 12, 9, 5, m[3]); + self.perm_elt(8, 7, 4, 1, 13, 10, 4, m[4]); + self.perm_elt(9, 8, 5, 2, 14, 11, 3, m[5]); + self.perm_elt(10, 9, 6, 3, 15, 12, 2, m[6]); + self.perm_elt(11, 10, 7, 4, 0, 13, 1, m[7]); + self.perm_elt(0, 11, 8, 5, 1, 14, 0, m[8]); + self.perm_elt(1, 0, 9, 6, 2, 15, 15, m[9]); + self.perm_elt(2, 1, 10, 7, 3, 0, 14, m[10]); + self.perm_elt(3, 2, 11, 8, 4, 1, 13, m[11]); + self.perm_elt(4, 3, 12, 9, 5, 2, 12, m[12]); + self.perm_elt(5, 4, 13, 10, 6, 3, 11, m[13]); + self.perm_elt(6, 5, 14, 11, 7, 4, 10, m[14]); + self.perm_elt(7, 6, 15, 12, 8, 5, 9, m[15]); + self.perm_elt(8, 7, 0, 13, 9, 6, 8, m[0]); + self.perm_elt(9, 8, 1, 14, 10, 7, 7, m[1]); + self.perm_elt(10, 9, 2, 15, 11, 8, 6, m[2]); + self.perm_elt(11, 10, 3, 0, 12, 9, 5, m[3]); + self.perm_elt(0, 11, 4, 1, 13, 10, 4, m[4]); + self.perm_elt(1, 0, 5, 2, 14, 11, 3, m[5]); + self.perm_elt(2, 1, 6, 3, 15, 12, 2, m[6]); + self.perm_elt(3, 2, 7, 4, 0, 13, 1, m[7]); + self.perm_elt(4, 3, 8, 5, 1, 14, 0, m[8]); + self.perm_elt(5, 4, 9, 6, 2, 15, 15, m[9]); + self.perm_elt(6, 5, 10, 7, 3, 0, 14, m[10]); + self.perm_elt(7, 6, 11, 8, 4, 1, 13, m[11]); + self.perm_elt(8, 7, 12, 9, 5, 2, 12, m[12]); + self.perm_elt(9, 8, 13, 10, 6, 3, 11, m[13]); + self.perm_elt(10, 9, 14, 11, 7, 4, 10, m[14]); + self.perm_elt(11, 10, 15, 12, 8, 5, 9, m[15]); + } + + fn swap_b_c(&mut self) { + mem::swap(&mut self.b, &mut self.c); + } +} + +#[inline] +fn read_m(input: &Block) -> [u32; 16] { + let mut m = [0u32; 16]; + for (o, chunk) in m.iter_mut().zip(input.chunks_exact(4)) { + *o = u32::from_le_bytes(chunk.try_into().unwrap()); + } + m +} + +pub(crate) fn compress(state: &mut EngineState, input: &Block) { + let m = read_m(input); + state.add_m(&m); + state.xor_w(); + state.perm(&m); + state.sub_m(&m); + state.swap_b_c(); + state.inc_w(); +} + +pub(crate) fn compress_final(state: &mut EngineState, input: &Block) { + let m = read_m(input); + state.add_m(&m); + state.xor_w(); + state.perm(&m); + for _ in 0..3 { + state.swap_b_c(); + state.xor_w(); + state.perm(&m); + } +} diff --git a/shabal/tests/data/shabal192.blb b/shabal/tests/data/shabal192.blb index b205df8a2..7eb0a8719 100644 Binary files a/shabal/tests/data/shabal192.blb and b/shabal/tests/data/shabal192.blb differ diff --git a/shabal/tests/data/shabal224.blb b/shabal/tests/data/shabal224.blb index 29de7decf..cdcb37f5f 100644 Binary files a/shabal/tests/data/shabal224.blb and b/shabal/tests/data/shabal224.blb differ diff --git a/shabal/tests/data/shabal256.blb b/shabal/tests/data/shabal256.blb index e978cb199..643aea8b1 100644 Binary files a/shabal/tests/data/shabal256.blb and b/shabal/tests/data/shabal256.blb differ diff --git a/shabal/tests/data/shabal384.blb b/shabal/tests/data/shabal384.blb index 266410a76..3dcbf4062 100644 Binary files a/shabal/tests/data/shabal384.blb and b/shabal/tests/data/shabal384.blb differ diff --git a/shabal/tests/data/shabal512.blb b/shabal/tests/data/shabal512.blb index d874809f7..2d57688f9 100644 Binary files a/shabal/tests/data/shabal512.blb and b/shabal/tests/data/shabal512.blb differ diff --git a/sm3/CHANGELOG.md b/sm3/CHANGELOG.md index 5f7b7bc8c..4d2d43146 100644 --- a/sm3/CHANGELOG.md +++ b/sm3/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## 0.4.0 (2021-11-22) +### Changed +- Update to `digest` v0.10 ([#217]) + +[#217]: https://github.com/RustCrypto/hashes/pull/217 + ## 0.3.0 (2021-07-18) ### Changed - RustCrypto SM3 release ([#249]) diff --git a/sm3/Cargo.toml b/sm3/Cargo.toml index 994a4f0cd..28fe163b2 100644 --- a/sm3/Cargo.toml +++ b/sm3/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "sm3" -version = "0.3.0" +version = "0.4.0" # Also update html_root_url in lib.rs when bumping this description = "SM3 (OSCCA GM/T 0004-2012) hash function" -authors = ["Tianjia Zhang "] +authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" readme = "README.md" edition = "2018" @@ -12,12 +12,10 @@ keywords = ["crypto", "sm3", "hash", "digest"] categories = ["cryptography", "no-std"] [dependencies] -digest = "0.9" -block-buffer = "0.9" -opaque-debug = "0.3" +digest = "0.10" [dev-dependencies] -digest = { version = "0.9", features = ["dev"] } +digest = { version = "0.10", features = ["dev"] } hex-literal = "0.2" [features] diff --git a/sm3/LICENSE-MIT b/sm3/LICENSE-MIT index 78d6d79a4..c869ada57 100644 --- a/sm3/LICENSE-MIT +++ b/sm3/LICENSE-MIT @@ -1,4 +1,4 @@ -Copyright (c) 2016 Artyom Pavlov +Copyright (c) 2021 The RustCrypto Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/sm3/examples/sm3sum.rs b/sm3/examples/sm3sum.rs deleted file mode 100644 index 94ec40810..000000000 --- a/sm3/examples/sm3sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use sm3::{Digest, Sm3}; -use std::env; -use std::fs; -use std::io::{self, Read}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = D::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/sm3/src/sm3.rs b/sm3/src/compress.rs similarity index 81% rename from sm3/src/sm3.rs rename to sm3/src/compress.rs index 42be5cf5c..731efb3c6 100644 --- a/sm3/src/sm3.rs +++ b/sm3/src/compress.rs @@ -1,67 +1,6 @@ -//! SM3 #![allow(clippy::many_single_char_names, clippy::too_many_arguments)] -use crate::consts::{SM3_IV, T32}; -use block_buffer::BlockBuffer; +use crate::{consts::T32, Block, Sm3Core}; use core::convert::TryInto; -use core::slice::from_ref; -use digest::consts::{U32, U64}; -use digest::generic_array::GenericArray; -use digest::{BlockInput, FixedOutputDirty, Reset, Update}; - -/// The SM3 hash algorithm with the SM3 initial hash value. -#[derive(Clone)] -pub struct Sm3 { - len: u64, - buffer: BlockBuffer, - state: [u32; 8], -} - -impl Default for Sm3 { - fn default() -> Self { - Sm3 { - len: 0, - buffer: Default::default(), - state: SM3_IV, - } - } -} - -impl BlockInput for Sm3 { - type BlockSize = U64; -} - -impl Update for Sm3 { - fn update(&mut self, input: impl AsRef<[u8]>) { - self.len += (input.as_ref().len() as u64) << 3; - let s = &mut self.state; - self.buffer - .input_blocks(input.as_ref(), |b| sm3_compress(s, b)); - } -} - -impl FixedOutputDirty for Sm3 { - type OutputSize = U32; - - fn finalize_into_dirty(&mut self, out: &mut digest::Output) { - let s = &mut self.state; - let l = self.len; - self.buffer - .len64_padding_be(l, |b| sm3_compress(s, from_ref(b))); - - let s = self.state; - for (chunk, v) in out.chunks_exact_mut(4).zip(s.iter()) { - chunk.copy_from_slice(&v.to_be_bytes()); - } - } -} - -impl Reset for Sm3 { - fn reset(&mut self) { - self.len = 0; - self.buffer.reset(); - self.state = SM3_IV; - } -} #[inline(always)] fn ff1(x: u32, y: u32, z: u32) -> u32 { @@ -209,7 +148,7 @@ macro_rules! R2 { }}; } -fn sm3_digest_block_u32(state: &mut [u32; 8], block: &[u32; 16]) { +fn compress_u32(state: &mut [u32; 8], block: &[u32; 16]) { let mut x: [u32; 16] = *block; let mut a = state[0]; @@ -296,15 +235,12 @@ fn sm3_digest_block_u32(state: &mut [u32; 8], block: &[u32; 16]) { state[7] ^= h; } -pub fn sm3_compress(state: &mut [u32; 8], blocks: &[GenericArray]) { - #[allow(unsafe_code)] - let blocks = unsafe { &*(blocks as *const _ as *const [[u8; 64]]) }; - - let mut w = [0u32; 16]; +pub(crate) fn compress(state: &mut [u32; 8], blocks: &[Block]) { for block in blocks { + let mut w = [0u32; 16]; for (o, chunk) in w.iter_mut().zip(block.chunks_exact(4)) { *o = u32::from_be_bytes(chunk.try_into().unwrap()); } - sm3_digest_block_u32(state, &w); + compress_u32(state, &w); } } diff --git a/sm3/src/consts.rs b/sm3/src/consts.rs index 1e997c221..792bdfbea 100644 --- a/sm3/src/consts.rs +++ b/sm3/src/consts.rs @@ -1,6 +1,6 @@ #![allow(clippy::unreadable_literal)] -pub const T32: [u32; 64] = [ +pub(crate) const T32: [u32; 64] = [ 0x79cc4519, 0xf3988a32, 0xe7311465, 0xce6228cb, 0x9cc45197, 0x3988a32f, 0x7311465e, 0xe6228cbc, 0xcc451979, 0x988a32f3, 0x311465e7, 0x6228cbce, 0xc451979c, 0x88a32f39, 0x11465e73, 0x228cbce6, 0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c, 0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce, @@ -11,6 +11,6 @@ pub const T32: [u32; 64] = [ 0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec, 0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5, ]; -pub static SM3_IV: [u32; 8] = [ +pub(crate) static H0: [u32; 8] = [ 0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e, ]; diff --git a/sm3/src/lib.rs b/sm3/src/lib.rs index ca9001d60..95062fa46 100644 --- a/sm3/src/lib.rs +++ b/sm3/src/lib.rs @@ -30,25 +30,102 @@ #![no_std] #![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_root_url = "https://docs.rs/sm3/0.4.0" )] #![deny(unsafe_code)] #![warn(missing_docs, rust_2018_idioms)] -#[cfg(feature = "std")] -extern crate std; +pub use digest::{self, Digest}; + +use core::{fmt, slice::from_ref}; +use digest::{ + block_buffer::Eager, + core_api::{ + AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore, + OutputSizeUser, Reset, UpdateCore, + }, + generic_array::typenum::{Unsigned, U32, U64}, + HashMarker, Output, +}; +mod compress; mod consts; -mod sm3; -pub use digest::{self, Digest}; +use compress::compress; + +/// Core SM3 hasher state. +#[derive(Clone)] +pub struct Sm3Core { + block_len: u64, + h: [u32; 8], +} + +impl HashMarker for Sm3Core {} + +impl BlockSizeUser for Sm3Core { + type BlockSize = U64; +} + +impl BufferKindUser for Sm3Core { + type BufferKind = Eager; +} + +impl OutputSizeUser for Sm3Core { + type OutputSize = U32; +} + +impl UpdateCore for Sm3Core { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + self.block_len += blocks.len() as u64; + compress(&mut self.h, blocks); + } +} + +impl FixedOutputCore for Sm3Core { + #[inline] + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + let bs = Self::BlockSize::U64; + let bit_len = 8 * (buffer.get_pos() as u64 + bs * self.block_len); + + let mut h = self.h; + buffer.len64_padding_be(bit_len, |b| compress(&mut h, from_ref(b))); + for (chunk, v) in out.chunks_exact_mut(4).zip(h.iter()) { + chunk.copy_from_slice(&v.to_be_bytes()); + } + } +} + +impl Default for Sm3Core { + #[inline] + fn default() -> Self { + Self { + h: consts::H0, + block_len: 0, + } + } +} -#[cfg(feature = "std")] -use digest::Update; +impl Reset for Sm3Core { + #[inline] + fn reset(&mut self) { + *self = Default::default(); + } +} -pub use crate::sm3::Sm3; +impl AlgorithmName for Sm3Core { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Sm3") + } +} -opaque_debug::implement!(Sm3); +impl fmt::Debug for Sm3Core { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Sm3Core { ... }") + } +} -digest::impl_write!(Sm3); +/// Sm3 hasher state. +pub type Sm3 = CoreWrapper; diff --git a/sm3/tests/data/sm3.blb b/sm3/tests/data/sm3.blb index 21d6e4b59..345e7cff2 100644 Binary files a/sm3/tests/data/sm3.blb and b/sm3/tests/data/sm3.blb differ diff --git a/sm3/tests/data/sm3_one_million_a.bin b/sm3/tests/data/sm3_one_million_a.bin deleted file mode 100644 index bbc7bd22d..000000000 --- a/sm3/tests/data/sm3_one_million_a.bin +++ /dev/null @@ -1,2 +0,0 @@ -Ȫ)U@)1* -%z:s+; \ No newline at end of file diff --git a/sm3/tests/lib.rs b/sm3/tests/lib.rs index 100ca6754..df5a9056d 100644 --- a/sm3/tests/lib.rs +++ b/sm3/tests/lib.rs @@ -1,28 +1,16 @@ use digest::dev::{digest_test, one_million_a}; use digest::new_test; +use hex_literal::hex; +use sm3::Sm3; -new_test!(sm3_main, "sm3", sm3::Sm3, digest_test); +new_test!(sm3_main, "sm3", Sm3, digest_test); -#[test] -fn sm3_1million_a() { - let output = include_bytes!("data/sm3_one_million_a.bin"); - one_million_a::(output); -} - -/// Test vectors from libgcrypt #[test] #[rustfmt::skip] -fn sm3_tests() { - use digest::Digest; - use hex_literal::hex; - - let hash = &mut sm3::Sm3::new(); - - hash.update(b"abc"); - assert_eq!(hash.finalize_reset().as_slice(), - hex!("66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0")); - - hash.update(b"abcdefghijklmnopqrstuvwxyz"); - assert_eq!(hash.finalize_reset().as_slice(), - hex!("b80fe97a4da24afc277564f66a359ef440462ad28dcc6d63adb24d5c20a61595")); +fn sm3_1million_a() { + let expected = hex!(" + c8aaf89429554029e231941a2acc0ad6 + 1ff2a5acd8fadd25847a3a732b3b02c3 + "); + one_million_a::(&expected); } diff --git a/streebog/CHANGELOG.md b/streebog/CHANGELOG.md index da35bcac0..45109f417 100644 --- a/streebog/CHANGELOG.md +++ b/streebog/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## 0.10.0 (2021-11-22) +### Changed +- Update to `digest` v0.10 ([#217]) + +[#217]: https://github.com/RustCrypto/hashes/pull/217 + ## 0.9.2 (2020-08-13) ### Changed - Documentation update ([#185]) diff --git a/streebog/Cargo.toml b/streebog/Cargo.toml index 7d8436b82..ade2b10d9 100644 --- a/streebog/Cargo.toml +++ b/streebog/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "streebog" -version = "0.9.2" +version = "0.10.0" # Also update html_root_url in lib.rs when bumping this description = "Streebog (GOST R 34.11-2012) hash function" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -12,12 +12,10 @@ keywords = ["crypto", "streebog", "gost", "hash", "digest"] categories = ["cryptography", "no-std"] [dependencies] -digest = "0.9" -block-buffer = { version = "0.9", features = ["block-padding"] } -opaque-debug = "0.3" +digest = "0.10" [dev-dependencies] -digest = { version = "0.9", features = ["dev"] } +digest = { version = "0.10", features = ["dev"] } hex-literal = "0.2" [features] diff --git a/streebog/examples/streebog256sum.rs b/streebog/examples/streebog256sum.rs deleted file mode 100644 index 4973d262a..000000000 --- a/streebog/examples/streebog256sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use std::env; -use std::fs; -use std::io::{self, Read}; -use streebog::{Digest, Streebog256}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = D::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/streebog/examples/streebog512sum.rs b/streebog/examples/streebog512sum.rs deleted file mode 100644 index e2130ff63..000000000 --- a/streebog/examples/streebog512sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use std::env; -use std::fs; -use std::io::{self, Read}; -use streebog::{Digest, Streebog512}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh = D::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/streebog/src/lib.rs b/streebog/src/lib.rs index 53fc7eb94..75c840d4e 100644 --- a/streebog/src/lib.rs +++ b/streebog/src/lib.rs @@ -2,34 +2,29 @@ //! in GOST R 34.11-2012. //! //! # Usage -//! Hasher functionality is expressed via traits defined in the [`digest`] -//! crate. -//! //! ```rust //! use streebog::{Digest, Streebog256, Streebog512}; //! use hex_literal::hex; //! -//! // create a hasher object, to use it do not forget to import `Digest` trait +//! // create Streebog256 hasher state //! let mut hasher = Streebog256::new(); //! // write input message -//! hasher.update(b"my"); -//! hasher.update(b" "); -//! hasher.update(b"message"); +//! hasher.update("The quick brown fox jumps over the lazy dog"); //! // read hash digest (it will consume hasher) //! let result = hasher.finalize(); //! //! assert_eq!(result[..], hex!(" -//! a47752ba9491bd1d52dd5dcea6d8c08e9b1ee70c42a2fc3e0d1a2852468c1329 +//! 3e7dea7f2384b6c5a3d0e24aaa29c05e89ddd762145030ec22c71a6db8b2c1f4 //! ")[..]); //! //! // same for Streebog512 //! let mut hasher = Streebog512::new(); -//! hasher.update(b"my message"); +//! hasher.update("The quick brown fox jumps over the lazy dog."); //! let result = hasher.finalize(); //! //! assert_eq!(result[..], hex!(" -//! c40cc26c37a683c74459820d884b766d9c96697a8d168c0272db8f4ecca2935b -//! 4164ede98fc9c8d2bafb1249b238676c81f5b97f98c393b99fdf2dc961391484 +//! fe0c42f267d921f940faa72bd9fcf84f9f1bd7e9d055e9816e4c2ace1ec83be8 +//! 2d2957cd59b86e123d8f5adee80b3ca08a017599a9fc1a14d940cf87c77df070 //! ")[..]); //! ``` //! @@ -40,10 +35,10 @@ #![no_std] #![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_root_url = "https://docs.rs/streebog/0.10.0" )] -#![deny(unsafe_code)] #![warn(missing_docs, rust_2018_idioms)] #[cfg(feature = "std")] @@ -51,22 +46,10 @@ extern crate std; mod consts; mod streebog; +mod streebog256; +mod streebog512; mod table; -use digest::consts::{U32, U64}; pub use digest::{self, Digest}; - -#[cfg(feature = "std")] -use digest::Update; - -/// Streebog-256 cryptographic hash function -pub type Streebog256 = streebog::Streebog; - -/// Streebog-512 cryptographic hash function -pub type Streebog512 = streebog::Streebog; - -opaque_debug::implement!(Streebog512); -opaque_debug::implement!(Streebog256); - -digest::impl_write!(Streebog512); -digest::impl_write!(Streebog256); +pub use streebog256::{Streebog256, Streebog256Core}; +pub use streebog512::{Streebog512, Streebog512Core}; diff --git a/streebog/src/streebog.rs b/streebog/src/streebog.rs index 9856d6621..18973d49d 100644 --- a/streebog/src/streebog.rs +++ b/streebog/src/streebog.rs @@ -1,8 +1,5 @@ -use block_buffer::{block_padding::ZeroPadding, BlockBuffer}; -use core::marker::PhantomData; -use digest::consts::U64; -use digest::generic_array::{ArrayLength, GenericArray}; -use digest::{BlockInput, FixedOutputDirty, Reset, Update}; +use core::convert::TryInto; +use digest::{block_buffer::EagerBuffer, consts::U64, generic_array::GenericArray}; use crate::consts::{BLOCK_SIZE, C}; use crate::table::SHUFFLED_LIN_TABLE; @@ -10,10 +7,10 @@ use crate::table::SHUFFLED_LIN_TABLE; type Block = [u8; 64]; #[derive(Copy, Clone)] -struct StreebogState { - h: Block, - n: Block, - sigma: Block, +pub(crate) struct StreebogState { + pub(crate) h: Block, + pub(crate) n: [u64; 8], + pub(crate) sigma: [u64; 8], } #[inline(always)] @@ -33,9 +30,7 @@ fn lps(h: &mut Block, n: &Block) { } } - for (chunk, v) in h.chunks_exact_mut(8).zip(buf.iter()) { - chunk.copy_from_slice(&v.to_le_bytes()); - } + *h = to_bytes(&buf); } impl StreebogState { @@ -60,126 +55,75 @@ impl StreebogState { } fn update_sigma(&mut self, m: &Block) { + let t = from_bytes(m); let mut carry = 0; - for (a, b) in self.sigma.iter_mut().zip(m.iter()) { - carry = (*a as u16) + (*b as u16) + (carry >> 8); - *a = (carry & 0xFF) as u8; - } + adc(&mut self.sigma[0], t[0], &mut carry); + adc(&mut self.sigma[1], t[1], &mut carry); + adc(&mut self.sigma[2], t[2], &mut carry); + adc(&mut self.sigma[3], t[3], &mut carry); + adc(&mut self.sigma[4], t[4], &mut carry); + adc(&mut self.sigma[5], t[5], &mut carry); + adc(&mut self.sigma[6], t[6], &mut carry); + adc(&mut self.sigma[7], t[7], &mut carry); } - fn update_n(&mut self, mut l: u8) { - let res = u16::from(self.n[0]) + (u16::from(l) << 3); - self.n[0] = (res & 0xff) as u8; - l = (res >> 8) as u8; - - for a in self.n.iter_mut().skip(1) { - let (res, over) = (*a).overflowing_add(l); - *a = res; - if over { - l = 1; - } else { - break; - } - } + fn update_n(&mut self, len: u64) { + let mut carry = 0; + // note: `len` can not be bigger than block size, + // so `8*len` will never overflow + adc(&mut self.n[0], 8 * len, &mut carry); + adc(&mut self.n[1], 0, &mut carry); + adc(&mut self.n[2], 0, &mut carry); + adc(&mut self.n[3], 0, &mut carry); + adc(&mut self.n[4], 0, &mut carry); + adc(&mut self.n[5], 0, &mut carry); + adc(&mut self.n[6], 0, &mut carry); + adc(&mut self.n[7], 0, &mut carry); } - fn process_block(&mut self, block: &GenericArray, msg_len: u8) { - #[allow(unsafe_code)] + fn compress(&mut self, block: &GenericArray, msg_len: u64) { let block = unsafe { &*(block.as_ptr() as *const [u8; 64]) }; - let n = self.n; - self.g(&n, block); + self.g(&to_bytes(&self.n), block); self.update_n(msg_len); self.update_sigma(block); } -} - -#[derive(Clone)] -pub struct Streebog + Copy> { - buffer: BlockBuffer, - state: StreebogState, - // Phantom data to tie digest size to the struct - digest_size: PhantomData, -} -impl Default for Streebog -where - N: ArrayLength + Copy, -{ - fn default() -> Self { - let h = match N::to_usize() { - 64 => [0u8; 64], - 32 => [1u8; 64], - _ => unreachable!(), - }; - Streebog { - buffer: Default::default(), - state: StreebogState { - h, - n: [0u8; 64], - sigma: [0u8; 64], - }, - digest_size: Default::default(), + pub(crate) fn update_blocks(&mut self, blocks: &[GenericArray]) { + for block in blocks { + self.compress(block, BLOCK_SIZE as u64); } } -} -impl BlockInput for Streebog -where - N: ArrayLength + Copy, -{ - type BlockSize = U64; + pub(crate) fn finalize(&mut self, buffer: &mut EagerBuffer) { + let pos = buffer.get_pos(); + // note that it's guaranteed that `compress` will be called only once + buffer.digest_pad(1, &[], |b| self.compress(b, pos as u64)); + self.g(&[0u8; 64], &to_bytes(&self.n)); + self.g(&[0u8; 64], &to_bytes(&self.sigma)); + } } -impl Update for Streebog -where - N: ArrayLength + Copy, -{ - fn update(&mut self, input: impl AsRef<[u8]>) { - let s = &mut self.state; - self.buffer - .input_block(input.as_ref(), |d| s.process_block(d, BLOCK_SIZE as u8)); - } +#[inline(always)] +fn adc(a: &mut u64, b: u64, carry: &mut u64) { + let ret = (*a as u128) + (b as u128) + (*carry as u128); + *a = ret as u64; + *carry = (ret >> 64) as u64; } -impl FixedOutputDirty for Streebog -where - N: ArrayLength + Copy, -{ - type OutputSize = N; - - fn finalize_into_dirty(&mut self, out: &mut GenericArray) { - let mut self_state = self.state; - let pos = self.buffer.position(); - - let block = self - .buffer - .pad_with::() - .expect("we never use input_lazy"); - block[pos] = 1; - self_state.process_block(block, pos as u8); - - let n = self_state.n; - self_state.g(&[0u8; 64], &n); - let sigma = self_state.sigma; - self_state.g(&[0u8; 64], &sigma); - - let n = BLOCK_SIZE - Self::OutputSize::to_usize(); - out.copy_from_slice(&self_state.h[n..]) +#[inline(always)] +fn to_bytes(b: &[u64; 8]) -> Block { + let mut t = [0; 64]; + for (chunk, v) in t.chunks_exact_mut(8).zip(b.iter()) { + chunk.copy_from_slice(&v.to_le_bytes()); } + t } -impl Reset for Streebog -where - N: ArrayLength + Copy, -{ - fn reset(&mut self) { - self.buffer.reset(); - self.state.h = match N::to_usize() { - 64 => [0u8; 64], - 32 => [1u8; 64], - _ => unreachable!(), - }; - self.state.n = [0; 64]; - self.state.sigma = [0; 64]; +#[inline(always)] +fn from_bytes(b: &Block) -> [u64; 8] { + let mut t = [0u64; 8]; + for (v, chunk) in t.iter_mut().zip(b.chunks_exact(8)) { + *v = u64::from_le_bytes(chunk.try_into().unwrap()); } + t } diff --git a/streebog/src/streebog256.rs b/streebog/src/streebog256.rs new file mode 100644 index 000000000..ef324b7c4 --- /dev/null +++ b/streebog/src/streebog256.rs @@ -0,0 +1,87 @@ +use core::fmt; +use digest::{ + block_buffer::Eager, + consts::{U32, U64}, + core_api::{ + AlgorithmName, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore, + OutputSizeUser, Reset, UpdateCore, + }, + generic_array::GenericArray, + HashMarker, +}; + +use crate::streebog::StreebogState; + +/// Core Streebog256 hasher state. +#[derive(Clone)] +pub struct Streebog256Core { + state: StreebogState, +} + +impl HashMarker for Streebog256Core {} + +impl BlockSizeUser for Streebog256Core { + type BlockSize = U64; +} + +impl BufferKindUser for Streebog256Core { + type BufferKind = Eager; +} + +impl OutputSizeUser for Streebog256Core { + type OutputSize = U32; +} + +impl UpdateCore for Streebog256Core { + #[inline] + fn update_blocks(&mut self, blocks: &[GenericArray]) { + self.state.update_blocks(blocks); + } +} + +impl FixedOutputCore for Streebog256Core { + #[inline] + fn finalize_fixed_core( + &mut self, + buffer: &mut Buffer, + out: &mut GenericArray, + ) { + self.state.finalize(buffer); + out.copy_from_slice(&self.state.h[32..]) + } +} + +impl Default for Streebog256Core { + #[inline(always)] + fn default() -> Self { + Self { + state: StreebogState { + h: [1u8; 64], + n: Default::default(), + sigma: Default::default(), + }, + } + } +} + +impl Reset for Streebog256Core { + #[inline(always)] + fn reset(&mut self) { + *self = Default::default(); + } +} + +impl AlgorithmName for Streebog256Core { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Streebog256") + } +} + +impl fmt::Debug for Streebog256Core { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Streebog256Core { ... }") + } +} + +/// Streebog256 hasher state. +pub type Streebog256 = CoreWrapper; diff --git a/streebog/src/streebog512.rs b/streebog/src/streebog512.rs new file mode 100644 index 000000000..63d36b350 --- /dev/null +++ b/streebog/src/streebog512.rs @@ -0,0 +1,82 @@ +use core::fmt; +use digest::{ + block_buffer::Eager, + consts::U64, + core_api::{ + AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore, + OutputSizeUser, Reset, UpdateCore, + }, + HashMarker, Output, +}; + +use crate::streebog::StreebogState; + +/// Core Streebog512 hasher state. +#[derive(Clone)] +pub struct Streebog512Core { + state: StreebogState, +} + +impl HashMarker for Streebog512Core {} + +impl BlockSizeUser for Streebog512Core { + type BlockSize = U64; +} + +impl BufferKindUser for Streebog512Core { + type BufferKind = Eager; +} + +impl OutputSizeUser for Streebog512Core { + type OutputSize = U64; +} + +impl UpdateCore for Streebog512Core { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + self.state.update_blocks(blocks); + } +} + +impl FixedOutputCore for Streebog512Core { + #[inline] + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + self.state.finalize(buffer); + out.copy_from_slice(&self.state.h) + } +} + +impl Default for Streebog512Core { + #[inline(always)] + fn default() -> Self { + Self { + state: StreebogState { + h: [0u8; 64], + n: Default::default(), + sigma: Default::default(), + }, + } + } +} + +impl Reset for Streebog512Core { + #[inline(always)] + fn reset(&mut self) { + *self = Default::default(); + } +} + +impl AlgorithmName for Streebog512Core { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Streebog512") + } +} + +impl fmt::Debug for Streebog512Core { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Streebog512Core { ... }") + } +} + +/// Streebog512 hasher state. +pub type Streebog512 = CoreWrapper; diff --git a/streebog/tests/data/streebog256.blb b/streebog/tests/data/streebog256.blb index af1df789e..149e1ec17 100644 Binary files a/streebog/tests/data/streebog256.blb and b/streebog/tests/data/streebog256.blb differ diff --git a/streebog/tests/data/streebog512.blb b/streebog/tests/data/streebog512.blb index a32fb4bc7..3de2dff70 100644 Binary files a/streebog/tests/data/streebog512.blb and b/streebog/tests/data/streebog512.blb differ diff --git a/tiger/CHANGELOG.md b/tiger/CHANGELOG.md index ed74940b2..83799cb53 100644 --- a/tiger/CHANGELOG.md +++ b/tiger/CHANGELOG.md @@ -5,5 +5,14 @@ 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). +## 0.2.0 (2021-11-22) +### Added +- `Tiger2` variant ([#217]) + +### Changed +- Update to `digest` v0.10 ([#217]) + +[#217]: https://github.com/RustCrypto/hashes/pull/217 + ## 0.1.0 (2021-02-05) - Initial release diff --git a/tiger/Cargo.toml b/tiger/Cargo.toml index 144833559..3e3c7171d 100644 --- a/tiger/Cargo.toml +++ b/tiger/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "tiger" -version = "0.1.0" +version = "0.2.0" # Also update html_root_url in lib.rs when bumping this description = "Tiger hash function" -authors = ["Ulrik Mikaelsson ", "RustCrypto Developers"] +authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" readme = "README.md" edition = "2018" @@ -12,12 +12,10 @@ keywords = ["crypto", "hash", "tiger", "digest"] categories = ["cryptography", "no-std"] [dependencies] -digest = "0.9" -block-buffer = { version = "0.9", features = ["block-padding"] } -byteorder = { version = "1", default-features = false } +digest = "0.10" [dev-dependencies] -digest = { version = "0.9", features = ["dev"] } +digest = { version = "0.10", features = ["dev"] } hex-literal = "0.2" [features] diff --git a/tiger/LICENSE-MIT b/tiger/LICENSE-MIT index d967eab37..d62c85c68 100644 --- a/tiger/LICENSE-MIT +++ b/tiger/LICENSE-MIT @@ -1,3 +1,4 @@ +Copyright (c) 2021 RustCrypto Developers Copyright (c) 2020 Ulrik Mikaelsson Permission is hereby granted, free of charge, to any diff --git a/tiger/src/compress.rs b/tiger/src/compress.rs new file mode 100644 index 000000000..20f7c56fc --- /dev/null +++ b/tiger/src/compress.rs @@ -0,0 +1,72 @@ +use super::tables::{T1, T2, T3, T4}; +use super::State; +use core::convert::TryInto; +use digest::generic_array::{typenum::U64, GenericArray}; + +#[inline(always)] +fn round(a: &mut u64, b: &mut u64, c: &mut u64, x: &u64, mul: u8) { + *c ^= *x; + let c2: [u8; 8] = c.to_le_bytes(); + let a2 = T1[usize::from(c2[0])] + ^ T2[usize::from(c2[2])] + ^ T3[usize::from(c2[4])] + ^ T4[usize::from(c2[6])]; + let b2 = T4[usize::from(c2[1])] + ^ T3[usize::from(c2[3])] + ^ T2[usize::from(c2[5])] + ^ T1[usize::from(c2[7])]; + *a = a.wrapping_sub(a2); + *b = b.wrapping_add(b2).wrapping_mul(u64::from(mul)); +} + +#[inline(always)] +fn pass(a: &mut u64, b: &mut u64, c: &mut u64, x: &[u64; 8], mul: u8) { + round(a, b, c, &x[0], mul); + round(b, c, a, &x[1], mul); + round(c, a, b, &x[2], mul); + round(a, b, c, &x[3], mul); + round(b, c, a, &x[4], mul); + round(c, a, b, &x[5], mul); + round(a, b, c, &x[6], mul); + round(b, c, a, &x[7], mul); +} + +#[inline(always)] +fn key_schedule(x: &mut [u64; 8]) { + x[0] = x[0].wrapping_sub(x[7] ^ 0xA5A5_A5A5_A5A5_A5A5); + x[1] ^= x[0]; + x[2] = x[2].wrapping_add(x[1]); + x[3] = x[3].wrapping_sub(x[2] ^ ((!x[1]) << 19)); + x[4] ^= x[3]; + x[5] = x[5].wrapping_add(x[4]); + x[6] = x[6].wrapping_sub(x[5] ^ ((!x[4]) >> 23)); + x[7] ^= x[6]; + x[0] = x[0].wrapping_add(x[7]); + x[1] = x[1].wrapping_sub(x[0] ^ ((!x[7]) << 19)); + x[2] ^= x[1]; + x[3] = x[3].wrapping_add(x[2]); + x[4] = x[4].wrapping_sub(x[3] ^ ((!x[2]) >> 23)); + x[5] ^= x[4]; + x[6] = x[6].wrapping_add(x[5]); + x[7] = x[7].wrapping_sub(x[6] ^ 0x0123_4567_89AB_CDEF); +} + +pub(crate) fn compress(state: &mut State, blocks: &[GenericArray]) { + let mut block: [u64; 8] = Default::default(); + for raw_block in blocks { + for (o, chunk) in block.iter_mut().zip(raw_block.chunks_exact(8)) { + *o = u64::from_le_bytes(chunk.try_into().unwrap()); + } + let [mut a, mut b, mut c] = *state; + + pass(&mut a, &mut b, &mut c, &block, 5); + key_schedule(&mut block); + pass(&mut c, &mut a, &mut b, &block, 7); + key_schedule(&mut block); + pass(&mut b, &mut c, &mut a, &block, 9); + + state[0] ^= a; + state[1] = b.wrapping_sub(state[1]); + state[2] = c.wrapping_add(state[2]); + } +} diff --git a/tiger/src/lib.rs b/tiger/src/lib.rs index 9996735a2..8ef93ca50 100644 --- a/tiger/src/lib.rs +++ b/tiger/src/lib.rs @@ -1,1264 +1,211 @@ -//! The [Tiger][1] hash function, implemented through [Digest][2] +//! An implementation of the [Tiger][1] cryptographic hash algorithms. //! -//! [1]: http://www.cs.technion.ac.il/~biham/Reports/Tiger/tiger/tiger.html -//! [2]: https://crates.io/crates/digest +//! Tiger2 is a variant of the original Tiger with a small padding tweak. +//! +//! # Usage +//! +//! ```rust +//! use hex_literal::hex; +//! use tiger::{Tiger, Digest}; +//! +//! // create a Tiger object +//! let mut hasher = Tiger::new(); +//! +//! // process input message +//! hasher.update(b"hello world"); +//! +//! // acquire hash digest in the form of GenericArray, +//! // which in this case is equivalent to [u8; 24] +//! let result = hasher.finalize(); +//! assert_eq!(result[..], hex!("4c8fbddae0b6f25832af45e7c62811bb64ec3e43691e9cc3")); +//! ``` +//! +//! Also see [RustCrypto/hashes][2] readme. +//! +//! [1]: https://en.wikipedia.org/wiki/Tiger_(hash_function) +//! [2]: https://github.com/RustCrypto/hashes #![no_std] #![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_root_url = "https://docs.rs/tiger/0.2.0" )] #![deny(unsafe_code)] #![warn(missing_docs, rust_2018_idioms)] -pub use digest; - -use block_buffer::{ - generic_array::typenum::consts::U64 as BB_U64, generic_array::GenericArray as BB_GenericArray, - BlockBuffer, +pub use digest::{self, Digest}; + +use core::{fmt, slice::from_ref}; +use digest::{ + block_buffer::Eager, + core_api::{ + AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore, + OutputSizeUser, Reset, UpdateCore, + }, + generic_array::typenum::{Unsigned, U24, U64}, + HashMarker, Output, }; -use byteorder::{ByteOrder, LE}; -use digest::generic_array::typenum::{U24, U64}; -use digest::generic_array::GenericArray; -type BlockBuffer512 = BlockBuffer; +mod compress; +mod tables; +use compress::compress; -const PADDING_BLOCK: [u8; 64] = [ - 1, 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, - 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, 0, -]; - -const H0: [u64; 3] = [ +type State = [u64; 3]; +const S0: State = [ 0x0123_4567_89AB_CDEF, 0xFEDC_BA98_7654_3210, 0xF096_A5B4_C3B2_E187, ]; -/// The Tiger hasher +/// Core Tiger hasher state. #[derive(Clone)] -pub struct Tiger { - length_bytes: u64, - buffer: BlockBuffer512, - state: [u64; 3], +pub struct TigerCore { + block_len: u64, + state: State, } -impl Default for Tiger { - fn default() -> Self { - Tiger { - length_bytes: 0, - buffer: Default::default(), - state: H0, - } - } +impl HashMarker for TigerCore {} + +impl BlockSizeUser for TigerCore { + type BlockSize = U64; +} + +impl BufferKindUser for TigerCore { + type BufferKind = Eager; } -impl Tiger { +impl OutputSizeUser for TigerCore { + type OutputSize = U24; +} + +impl UpdateCore for TigerCore { #[inline] - fn fill_up_to(from: usize, to: usize, modulo: usize) -> usize { - let _from = from + 1; - let _to = to + modulo; - 1 + ((_to - _from) % modulo) + fn update_blocks(&mut self, blocks: &[Block]) { + self.block_len += blocks.len() as u64; + compress(&mut self.state, blocks); } +} +impl FixedOutputCore for TigerCore { #[inline] - fn finalize(&mut self) -> [u64; 3] { - { - let self_state = &mut self.state; - let pad_size = Self::fill_up_to(self.buffer.position(), 64 - 8, 64); - self.buffer.input_block(&PADDING_BLOCK[..pad_size], |d| { - Self::compress(self_state, d) - }); - - let mut length: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0]; - LE::write_u64(&mut length, (self.length_bytes << 3) as u64); - self.buffer - .input_block(&length, |d| Self::compress(self_state, d)); - - assert_eq!(self.buffer.position(), 0); + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + let bs = Self::BlockSize::U64 as u64; + let pos = buffer.get_pos() as u64; + let bit_len = 8 * (pos + bs * self.block_len); + + buffer.digest_pad(1, &bit_len.to_le_bytes(), |b| { + compress(&mut self.state, from_ref(b)) + }); + for (chunk, v) in out.chunks_exact_mut(8).zip(self.state.iter()) { + chunk.copy_from_slice(&v.to_le_bytes()); } - self.state } +} - fn consume(&mut self, input: &[u8]) { - // Unlike Sha1 and Sha2, the length value in Tiger is defined as - // the length of the message mod 2^64 - ie: integer overflow is OK. - self.length_bytes += input.len() as u64; - let self_state = &mut self.state; - self.buffer - .input_block(input, |d| Self::compress(self_state, d)); +impl Default for TigerCore { + fn default() -> Self { + Self { + block_len: 0, + state: S0, + } } +} - #[inline] - fn compress(state: &mut [u64; 3], input: &BB_GenericArray) { - let mut inputs: [u64; 8] = Default::default(); - LE::read_u64_into(input, &mut inputs); - let mut a = state[0]; - let mut b = state[1]; - let mut c = state[2]; - - Self::pass(&mut a, &mut b, &mut c, &inputs, 5); - Self::key_schedule(&mut inputs); - Self::pass(&mut c, &mut a, &mut b, &inputs, 7); - Self::key_schedule(&mut inputs); - Self::pass(&mut b, &mut c, &mut a, &inputs, 9); - - state[0] ^= a; - state[1] = b.wrapping_sub(state[1]); - state[2] = c.wrapping_add(state[2]); +impl Reset for TigerCore { + fn reset(&mut self) { + *self = Default::default(); } +} - #[inline] - fn pass(a: &mut u64, b: &mut u64, c: &mut u64, x: &[u64; 8], mul: u8) { - Self::round(a, b, c, &x[0], mul); - Self::round(b, c, a, &x[1], mul); - Self::round(c, a, b, &x[2], mul); - Self::round(a, b, c, &x[3], mul); - Self::round(b, c, a, &x[4], mul); - Self::round(c, a, b, &x[5], mul); - Self::round(a, b, c, &x[6], mul); - Self::round(b, c, a, &x[7], mul); +impl AlgorithmName for TigerCore { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Tiger") } +} - #[inline] - #[allow(clippy::trivially_copy_pass_by_ref)] - fn round(a: &mut u64, b: &mut u64, c: &mut u64, x: &u64, mul: u8) { - *c ^= *x; - let mut c_: [u8; 8] = Default::default(); - LE::write_u64(&mut c_, *c); - *a = a.wrapping_sub( - T1[c_[0] as usize] ^ T2[c_[2] as usize] ^ T3[c_[4] as usize] ^ T4[c_[6] as usize], - ); - *b = b.wrapping_add( - T4[c_[1] as usize] ^ T3[c_[3] as usize] ^ T2[c_[5] as usize] ^ T1[c_[7] as usize], - ); - *b = b.wrapping_mul(u64::from(mul)); +impl fmt::Debug for TigerCore { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("TigerCore { ... }") } +} - #[inline] - fn key_schedule(x: &mut [u64; 8]) { - x[0] = x[0].wrapping_sub(x[7] ^ 0xA5A5_A5A5_A5A5_A5A5); - x[1] ^= x[0]; - x[2] = x[2].wrapping_add(x[1]); - x[3] = x[3].wrapping_sub(x[2] ^ ((!x[1]) << 19)); - x[4] ^= x[3]; - x[5] = x[5].wrapping_add(x[4]); - x[6] = x[6].wrapping_sub(x[5] ^ ((!x[4]) >> 23)); - x[7] ^= x[6]; - x[0] = x[0].wrapping_add(x[7]); - x[1] = x[1].wrapping_sub(x[0] ^ ((!x[7]) << 19)); - x[2] ^= x[1]; - x[3] = x[3].wrapping_add(x[2]); - x[4] = x[4].wrapping_sub(x[3] ^ ((!x[2]) >> 23)); - x[5] ^= x[4]; - x[6] = x[6].wrapping_add(x[5]); - x[7] = x[7].wrapping_sub(x[6] ^ 0x0123_4567_89AB_CDEF); - } +/// Core Tiger2 hasher state. +#[derive(Clone)] +pub struct Tiger2Core { + block_len: u64, + state: State, } -impl digest::BlockInput for Tiger { +impl HashMarker for Tiger2Core {} + +impl BlockSizeUser for Tiger2Core { type BlockSize = U64; } -impl digest::Reset for Tiger { - fn reset(&mut self) { - self.buffer.reset(); - self.length_bytes = 0; - self.state = H0; - } +impl BufferKindUser for Tiger2Core { + type BufferKind = Eager; } -impl digest::Update for Tiger { - #[inline] +impl OutputSizeUser for Tiger2Core { + type OutputSize = U24; +} - fn update(&mut self, data: impl AsRef<[u8]>) { - self.consume(data.as_ref()); +impl UpdateCore for Tiger2Core { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + self.block_len += blocks.len() as u64; + compress(&mut self.state, blocks); } } -impl digest::FixedOutputDirty for Tiger { - type OutputSize = U24; - - fn finalize_into_dirty(&mut self, out: &mut GenericArray) { - LE::write_u64_into(&self.finalize(), &mut out.as_mut_slice()); +impl FixedOutputCore for Tiger2Core { + #[inline] + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + let bs = Self::BlockSize::U64 as u64; + let pos = buffer.get_pos() as u64; + let bit_len = 8 * (pos + bs * self.block_len); + + buffer.len64_padding_le(bit_len, |b| compress(&mut self.state, from_ref(b))); + for (chunk, v) in out.chunks_exact_mut(8).zip(self.state.iter()) { + chunk.copy_from_slice(&v.to_le_bytes()); + } } } -// Conditionally compile the module `test` only when the test-suite is run. -#[cfg(test)] -mod test { - use super::Tiger; - use digest::Digest; - use hex_literal::hex; +impl Default for Tiger2Core { + fn default() -> Self { + Self { + block_len: 0, + state: [ + 0x0123_4567_89AB_CDEF, + 0xFEDC_BA98_7654_3210, + 0xF096_A5B4_C3B2_E187, + ], + } + } +} - #[test] - fn test_vectors() { - let examples = [ - ("", hex!("3293ac630c13f0245f92bbb1766e16167a4e58492dde73f3")), - ("abc", hex!("2aab1484e8c158f2bfb8c5ff41b57a525129131c957b5f93")), - ("Tiger", hex!("dd00230799f5009fec6debc838bb6a27df2b9d6f110c7937")), - ( - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", - hex!("f71c8583902afb879edfe610f82c0d4786a3a534504486b5"), - ), - ( - "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789", - hex!("48ceeb6308b87d46e95d656112cdf18d97915f9765658957"), - ), - ( - "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham", - hex!("8a866829040a410c729ad23f5ada711603b3cdd357e4c15e"), - ), - ( - "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge.", - hex!("ce55a6afd591f5ebac547ff84f89227f9331dab0b611c889"), - ), - ( - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - hex!("0f7bf9a19b9c58f2b7610df7e84f0ac3a71c631e7b53f78e"), - ), - ( - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - hex!("08c8dcb467e4c7f910966c399fdc9b164be15b792d432224"), - ), - ]; +impl Reset for Tiger2Core { + #[inline] + fn reset(&mut self) { + *self = Default::default(); + } +} - for &(input, answer) in examples.iter() { - let result = Tiger::digest(input.as_bytes()); +impl AlgorithmName for Tiger2Core { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Tiger2") + } +} - assert_eq!(*result, answer); - } +impl fmt::Debug for Tiger2Core { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Tiger2Core { ... }") } } -static T1: [u64; 256] = [ - 0x02AA_B17C_F7E9_0C5E, /* 0 */ - 0xAC42_4B03_E243_A8EC, /* 1 */ - 0x72CD_5BE3_0DD5_FCD3, /* 2 */ - 0x6D01_9B93_F6F9_7F3A, /* 3 */ - 0xCD99_78FF_D21F_9193, /* 4 */ - 0x7573_A1C9_7080_29E2, /* 5 */ - 0xB164_326B_922A_83C3, /* 6 */ - 0x4688_3EEE_0491_5870, /* 7 */ - 0xEAAC_E305_7103_ECE6, /* 8 */ - 0xC541_69B8_08A3_535C, /* 9 */ - 0x4CE7_5491_8DDE_C47C, /* 10 */ - 0x0AA2_F4DF_DC0D_F40C, /* 11 */ - 0x10B7_6F18_A74D_BEFA, /* 12 */ - 0xC6CC_B623_5AD1_AB6A, /* 13 */ - 0x1372_6121_572F_E2FF, /* 14 */ - 0x1A48_8C6F_199D_921E, /* 15 */ - 0x4BC9_F9F4_DA00_07CA, /* 16 */ - 0x26F5_E6F6_E852_41C7, /* 17 */ - 0x8590_79DB_EA59_47B6, /* 18 */ - 0x4F18_85C5_C99E_8C92, /* 19 */ - 0xD78E_761E_A96F_864B, /* 20 */ - 0x8E36_428C_52B5_C17D, /* 21 */ - 0x69CF_6827_3730_63C1, /* 22 */ - 0xB607_C93D_9BB4_C56E, /* 23 */ - 0x7D82_0E76_0E76_B5EA, /* 24 */ - 0x645C_9CC6_F07F_DC42, /* 25 */ - 0xBF38_A078_2433_42E0, /* 26 */ - 0x5F6B_343C_9D2E_7D04, /* 27 */ - 0xF2C2_8AEB_600B_0EC6, /* 28 */ - 0x6C0E_D85F_7254_BCAC, /* 29 */ - 0x7159_2281_A4DB_4FE5, /* 30 */ - 0x1967_FA69_CE0F_ED9F, /* 31 */ - 0xFD52_93F8_B965_45DB, /* 32 */ - 0xC879_E9D7_F2A7_600B, /* 33 */ - 0x8602_4892_0193_194E, /* 34 */ - 0xA4F9_533B_2D9C_C0B3, /* 35 */ - 0x9053_836C_1595_7613, /* 36 */ - 0xDB6D_CF8A_FC35_7BF1, /* 37 */ - 0x18BE_EA7A_7A37_0F57, /* 38 */ - 0x0371_17CA_50B9_9066, /* 39 */ - 0x6AB3_0A97_7442_4A35, /* 40 */ - 0xF4E9_2F02_E325_249B, /* 41 */ - 0x7739_DB07_061C_CAE1, /* 42 */ - 0xD8F3_B49C_ECA4_2A05, /* 43 */ - 0xBD56_BE3F_5138_2F73, /* 44 */ - 0x45FA_ED58_43B0_BB28, /* 45 */ - 0x1C81_3D5C_11BF_1F83, /* 46 */ - 0x8AF0_E4B6_D75F_A169, /* 47 */ - 0x33EE_18A4_87AD_9999, /* 48 */ - 0x3C26_E8EA_B1C9_4410, /* 49 */ - 0xB510_102B_C0A8_22F9, /* 50 */ - 0x141E_EF31_0CE6_123B, /* 51 */ - 0xFC65_B900_59DD_B154, /* 52 */ - 0xE015_8640_C5E0_E607, /* 53 */ - 0x884E_0798_26C3_A3CF, /* 54 */ - 0x930D_0D95_23C5_35FD, /* 55 */ - 0x3563_8D75_4E9A_2B00, /* 56 */ - 0x4085_FCCF_4046_9DD5, /* 57 */ - 0xC4B1_7AD2_8BE2_3A4C, /* 58 */ - 0xCAB2_F0FC_6A3E_6A2E, /* 59 */ - 0x2860_971A_6B94_3FCD, /* 60 */ - 0x3DDE_6EE2_12E3_0446, /* 61 */ - 0x6222_F32A_E017_65AE, /* 62 */ - 0x5D55_0BB5_4783_08FE, /* 63 */ - 0xA9EF_A98D_A0ED_A22A, /* 64 */ - 0xC351_A716_86C4_0DA7, /* 65 */ - 0x1105_586D_9C86_7C84, /* 66 */ - 0xDCFF_EE85_FDA2_2853, /* 67 */ - 0xCCFB_D026_2C5E_EF76, /* 68 */ - 0xBAF2_94CB_8990_D201, /* 69 */ - 0xE694_64F5_2AFA_D975, /* 70 */ - 0x94B0_13AF_DF13_3E14, /* 71 */ - 0x06A7_D1A3_2823_C958, /* 72 */ - 0x6F95_FE51_30F6_1119, /* 73 */ - 0xD92A_B34E_462C_06C0, /* 74 */ - 0xED7B_DE33_887C_71D2, /* 75 */ - 0x7974_6D6E_6518_393E, /* 76 */ - 0x5BA4_1938_5D71_3329, /* 77 */ - 0x7C1B_A6B9_48A9_7564, /* 78 */ - 0x3198_7C19_7BFD_AC67, /* 79 */ - 0xDE6C_23C4_4B05_3D02, /* 80 */ - 0x581C_49FE_D002_D64D, /* 81 */ - 0xDD47_4D63_3826_1571, /* 82 */ - 0xAA45_46C3_E473_D062, /* 83 */ - 0x928F_CE34_9455_F860, /* 84 */ - 0x4816_1BBA_CAAB_94D9, /* 85 */ - 0x6391_2430_770E_6F68, /* 86 */ - 0x6EC8_A5E6_02C6_641C, /* 87 */ - 0x8728_2515_337D_DD2B, /* 88 */ - 0x2CDA_6B42_034B_701B, /* 89 */ - 0xB03D_37C1_81CB_096D, /* 90 */ - 0xE108_4382_66C7_1C6F, /* 91 */ - 0x2B31_80C7_EB51_B255, /* 92 */ - 0xDF92_B82F_96C0_8BBC, /* 93 */ - 0x5C68_C8C0_A632_F3BA, /* 94 */ - 0x5504_CC86_1C3D_0556, /* 95 */ - 0xABBF_A4E5_5FB2_6B8F, /* 96 */ - 0x4184_8B0A_B3BA_CEB4, /* 97 */ - 0xB334_A273_AA44_5D32, /* 98 */ - 0xBCA6_96F0_A85A_D881, /* 99 */ - 0x24F6_EC65_B528_D56C, /* 100 */ - 0x0CE1_512E_90F4_524A, /* 101 */ - 0x4E9D_D79D_5506_D35A, /* 102 */ - 0x2589_05FA_C6CE_9779, /* 103 */ - 0x2019_295B_3E10_9B33, /* 104 */ - 0xF8A9_478B_73A0_54CC, /* 105 */ - 0x2924_F2F9_3441_7EB0, /* 106 */ - 0x3993_357D_536D_1BC4, /* 107 */ - 0x38A8_1AC2_1DB6_FF8B, /* 108 */ - 0x47C4_FBF1_7D60_16BF, /* 109 */ - 0x1E0F_AADD_7667_E3F5, /* 110 */ - 0x7ABC_FF62_938B_EB96, /* 111 */ - 0xA78D_AD94_8FC1_79C9, /* 112 */ - 0x8F1F_98B7_2911_E50D, /* 113 */ - 0x61E4_8EAE_2712_1A91, /* 114 */ - 0x4D62_F7AD_3185_9808, /* 115 */ - 0xECEB_A345_EF5C_EAEB, /* 116 */ - 0xF5CE_B25E_BC96_84CE, /* 117 */ - 0xF633_E20C_B7F7_6221, /* 118 */ - 0xA32C_DF06_AB82_93E4, /* 119 */ - 0x985A_202C_A5EE_2CA4, /* 120 */ - 0xCF0B_8447_CC8A_8FB1, /* 121 */ - 0x9F76_5244_9798_59A3, /* 122 */ - 0xA8D5_16B1_A124_0017, /* 123 */ - 0x0BD7_BA3E_BB5D_C726, /* 124 */ - 0xE54B_CA55_B86A_DB39, /* 125 */ - 0x1D7A_3AFD_6C47_8063, /* 126 */ - 0x519E_C608_E766_9EDD, /* 127 */ - 0x0E57_15A2_D149_AA23, /* 128 */ - 0x177D_4571_848F_F194, /* 129 */ - 0xEEB5_5F32_4101_4C22, /* 130 */ - 0x0F5E_5CA1_3A6E_2EC2, /* 131 */ - 0x8029_927B_75F5_C361, /* 132 */ - 0xAD13_9FAB_C3D6_E436, /* 133 */ - 0x0D5D_F1A9_4CCF_402F, /* 134 */ - 0x3E8B_D948_BEA5_DFC8, /* 135 */ - 0xA5A0_D357_BD3F_F77E, /* 136 */ - 0xA2D1_2E25_1F74_F645, /* 137 */ - 0x66FD_9E52_5E81_A082, /* 138 */ - 0x2E0C_90CE_7F68_7A49, /* 139 */ - 0xC2E8_BCBE_BA97_3BC5, /* 140 */ - 0x0000_01BC_E509_745F, /* 141 */ - 0x4237_77BB_E6DA_B3D6, /* 142 */ - 0xD166_1C7E_AEF0_6EB5, /* 143 */ - 0xA178_1F35_4DAA_CFD8, /* 144 */ - 0x2D11_284A_2B16_AFFC, /* 145 */ - 0xF1FC_4F67_FA89_1D1F, /* 146 */ - 0x73EC_C25D_CB92_0ADA, /* 147 */ - 0xAE61_0C22_C2A1_2651, /* 148 */ - 0x96E0_A810_D356_B78A, /* 149 */ - 0x5A9A_381F_2FE7_870F, /* 150 */ - 0xD5AD_62ED_E94E_5530, /* 151 */ - 0xD225_E5E8_368D_1427, /* 152 */ - 0x6597_7B70_C7AF_4631, /* 153 */ - 0x99F8_89B2_DE39_D74F, /* 154 */ - 0x233F_30BF_54E1_D143, /* 155 */ - 0x9A96_75D3_D9A6_3C97, /* 156 */ - 0x5470_554F_F334_F9A8, /* 157 */ - 0x166A_CB74_4A4F_5688, /* 158 */ - 0x70C7_4CAA_B2E4_AEAD, /* 159 */ - 0xF0D0_9164_6F29_4D12, /* 160 */ - 0x57B8_2A89_6840_31D1, /* 161 */ - 0xEFD9_5A5A_61BE_0B6B, /* 162 */ - 0x2FBD_12E9_69F2_F29A, /* 163 */ - 0x9BD3_7013_FEFF_9FE8, /* 164 */ - 0x3F9B_0404_D608_5A06, /* 165 */ - 0x4940_C1F3_166C_FE15, /* 166 */ - 0x0954_2C4D_CDF3_DEFB, /* 167 */ - 0xB4C5_2183_85CD_5CE3, /* 168 */ - 0xC935_B7DC_4462_A641, /* 169 */ - 0x3417_F8A6_8ED3_B63F, /* 170 */ - 0xB809_5929_5B21_5B40, /* 171 */ - 0xF99C_DAEF_3B8C_8572, /* 172 */ - 0x018C_0614_F8FC_B95D, /* 173 */ - 0x1B14_ACCD_1A3A_CDF3, /* 174 */ - 0x84D4_71F2_00BB_732D, /* 175 */ - 0xC1A3_110E_95E8_DA16, /* 176 */ - 0x430A_7220_BF1A_82B8, /* 177 */ - 0xB77E_090D_39DF_210E, /* 178 */ - 0x5EF4_BD9F_3CD0_5E9D, /* 179 */ - 0x9D4F_F6DA_7E57_A444, /* 180 */ - 0xDA1D_60E1_83D4_A5F8, /* 181 */ - 0xB287_C384_1799_8E47, /* 182 */ - 0xFE3E_DC12_1BB3_1886, /* 183 */ - 0xC7FE_3CCC_980C_CBEF, /* 184 */ - 0xE46F_B590_189B_FD03, /* 185 */ - 0x3732_FD46_9A4C_57DC, /* 186 */ - 0x7EF7_00A0_7CF1_AD65, /* 187 */ - 0x59C6_4468_A31D_8859, /* 188 */ - 0x762F_B0B4_D45B_61F6, /* 189 */ - 0x155B_AED0_9904_7718, /* 190 */ - 0x6875_5E4C_3D50_BAA6, /* 191 */ - 0xE921_4E7F_22D8_B4DF, /* 192 */ - 0x2ADD_BF53_2EAC_95F4, /* 193 */ - 0x32AE_3909_B4BD_0109, /* 194 */ - 0x834D_F537_B08E_3450, /* 195 */ - 0xFA20_9DA8_4220_728D, /* 196 */ - 0x9E69_1D9B_9EFE_23F7, /* 197 */ - 0x0446_D288_C4AE_8D7F, /* 198 */ - 0x7B4C_C524_E169_785B, /* 199 */ - 0x21D8_7F01_35CA_1385, /* 200 */ - 0xCEBB_400F_137B_8AA5, /* 201 */ - 0x272E_2B66_5807_96BE, /* 202 */ - 0x3612_2641_25C2_B0DE, /* 203 */ - 0x0577_02BD_AD1E_FBB2, /* 204 */ - 0xD4BA_BB8E_ACF8_4BE9, /* 205 */ - 0x9158_3139_641B_C67B, /* 206 */ - 0x8BDC_2DE0_8036_E024, /* 207 */ - 0x603C_8156_F49F_68ED, /* 208 */ - 0xF7D2_36F7_DBEF_5111, /* 209 */ - 0x9727_C459_8AD2_1E80, /* 210 */ - 0xA08A_0896_670A_5FD7, /* 211 */ - 0xCB4A_8F43_09EB_A9CB, /* 212 */ - 0x81AF_564B_0F70_36A1, /* 213 */ - 0xC0B9_9AA7_7819_9ABD, /* 214 */ - 0x959F_1EC8_3FC8_E952, /* 215 */ - 0x8C50_5077_794A_81B9, /* 216 */ - 0x3ACA_AF8F_0563_38F0, /* 217 */ - 0x07B4_3F50_627A_6778, /* 218 */ - 0x4A44_AB49_F5EC_CC77, /* 219 */ - 0x3BC3_D6E4_B679_EE98, /* 220 */ - 0x9CC0_D4D1_CF14_108C, /* 221 */ - 0x4406_C00B_206B_C8A0, /* 222 */ - 0x82A1_8854_C8D7_2D89, /* 223 */ - 0x67E3_66B3_5C3C_432C, /* 224 */ - 0xB923_DD61_102B_37F2, /* 225 */ - 0x56AB_2779_D884_271D, /* 226 */ - 0xBE83_E1B0_FF15_25AF, /* 227 */ - 0xFB7C_65D4_217E_49A9, /* 228 */ - 0x6BDB_E0E7_6D48_E7D4, /* 229 */ - 0x08DF_8287_45D9_179E, /* 230 */ - 0x22EA_6A9A_DD53_BD34, /* 231 */ - 0xE36E_141C_5622_200A, /* 232 */ - 0x7F80_5D1B_8CB7_50EE, /* 233 */ - 0xAFE5_C7A5_9F58_E837, /* 234 */ - 0xE27F_996A_4FB1_C23C, /* 235 */ - 0xD386_7DFB_0775_F0D0, /* 236 */ - 0xD0E6_73DE_6E88_891A, /* 237 */ - 0x123A_EB9E_AFB8_6C25, /* 238 */ - 0x30F1_D5D5_C145_B895, /* 239 */ - 0xBB43_4A2D_EE72_69E7, /* 240 */ - 0x78CB_67EC_F931_FA38, /* 241 */ - 0xF33B_0372_323B_BF9C, /* 242 */ - 0x52D6_6336_FB27_9C74, /* 243 */ - 0x505F_33AC_0AFB_4EAA, /* 244 */ - 0xE8A5_CD99_A2CC_E187, /* 245 */ - 0x5349_7480_1E2D_30BB, /* 246 */ - 0x8D2D_5711_D587_6D90, /* 247 */ - 0x1F1A_4128_91BC_038E, /* 248 */ - 0xD6E2_E71D_82E5_6648, /* 249 */ - 0x7403_6C3A_4977_32B7, /* 250 */ - 0x89B6_7ED9_6361_F5AB, /* 251 */ - 0xFFED_95D8_F1EA_02A2, /* 252 */ - 0xE72B_3BD6_1464_D43D, /* 253 */ - 0xA630_0F17_0BDC_4820, /* 254 */ - 0xEBC1_8760_ED78_A77A, /* 255 */ -]; -static T2: [u64; 256] = [ - 0xE6A6_BE5A_05A1_2138, /* 256 */ - 0xB5A1_22A5_B4F8_7C98, /* 257 */ - 0x563C_6089_140B_6990, /* 258 */ - 0x4C46_CB2E_391F_5DD5, /* 259 */ - 0xD932_ADDB_C9B7_9434, /* 260 */ - 0x08EA_70E4_2015_AFF5, /* 261 */ - 0xD765_A667_3E47_8CF1, /* 262 */ - 0xC4FB_757E_AB27_8D99, /* 263 */ - 0xDF11_C686_2D6E_0692, /* 264 */ - 0xDDEB_84F1_0D7F_3B16, /* 265 */ - 0x6F2E_F604_A665_EA04, /* 266 */ - 0x4A8E_0F0F_F0E0_DFB3, /* 267 */ - 0xA5ED_EEF8_3DBC_BA51, /* 268 */ - 0xFC4F_0A2A_0EA4_371E, /* 269 */ - 0xE83E_1DA8_5CB3_8429, /* 270 */ - 0xDC8F_F882_BA1B_1CE2, /* 271 */ - 0xCD45_505E_8353_E80D, /* 272 */ - 0x18D1_9A00_D4DB_0717, /* 273 */ - 0x34A0_CFED_A5F3_8101, /* 274 */ - 0x0BE7_7E51_8887_CAF2, /* 275 */ - 0x1E34_1438_B3C4_5136, /* 276 */ - 0xE057_97F4_9089_CCF9, /* 277 */ - 0xFFD2_3F9D_F259_1D14, /* 278 */ - 0x543D_DA22_8595_C5CD, /* 279 */ - 0x661F_81FD_9905_2A33, /* 280 */ - 0x8736_E641_DB0F_7B76, /* 281 */ - 0x1522_7725_418E_5307, /* 282 */ - 0xE25F_7F46_162E_B2FA, /* 283 */ - 0x48A8_B212_6C13_D9FE, /* 284 */ - 0xAFDC_5417_92E7_6EEA, /* 285 */ - 0x03D9_12BF_C6D1_898F, /* 286 */ - 0x31B1_AAFA_1B83_F51B, /* 287 */ - 0xF1AC_2796_E42A_B7D9, /* 288 */ - 0x40A3_A7D7_FCD2_EBAC, /* 289 */ - 0x1056_136D_0AFB_BCC5, /* 290 */ - 0x7889_E1DD_9A6D_0C85, /* 291 */ - 0xD335_2578_2A79_74AA, /* 292 */ - 0xA7E2_5D09_078A_C09B, /* 293 */ - 0xBD41_38B3_EAC6_EDD0, /* 294 */ - 0x920A_BFBE_71EB_9E70, /* 295 */ - 0xA2A5_D0F5_4FC2_625C, /* 296 */ - 0xC054_E36B_0B12_90A3, /* 297 */ - 0xF6DD_59FF_62FE_932B, /* 298 */ - 0x3537_3545_11A8_AC7D, /* 299 */ - 0xCA84_5E91_72FA_DCD4, /* 300 */ - 0x84F8_2B60_329D_20DC, /* 301 */ - 0x79C6_2CE1_CD67_2F18, /* 302 */ - 0x8B09_A2AD_D124_642C, /* 303 */ - 0xD0C1_E96A_19D9_E726, /* 304 */ - 0x5A78_6A9B_4BA9_500C, /* 305 */ - 0x0E02_0336_634C_43F3, /* 306 */ - 0xC17B_474A_EB66_D822, /* 307 */ - 0x6A73_1AE3_EC9B_AAC2, /* 308 */ - 0x8226_667A_E084_0258, /* 309 */ - 0x67D4_5676_91CA_ECA5, /* 310 */ - 0x1D94_155C_4875_ADB5, /* 311 */ - 0x6D00_FD98_5B81_3FDF, /* 312 */ - 0x5128_6EFC_B774_CD06, /* 313 */ - 0x5E88_3447_1FA7_44AF, /* 314 */ - 0xF72C_A0AE_E761_AE2E, /* 315 */ - 0xBE40_E4CD_AEE8_E09A, /* 316 */ - 0xE997_0BBB_5118_F665, /* 317 */ - 0x726E_4BEB_33DF_1964, /* 318 */ - 0x703B_0007_2919_9762, /* 319 */ - 0x4631_D816_F5EF_30A7, /* 320 */ - 0xB880_B5B5_1504_A6BE, /* 321 */ - 0x6417_93C3_7ED8_4B6C, /* 322 */ - 0x7B21_ED77_F6E9_7D96, /* 323 */ - 0x7763_0631_2EF9_6B73, /* 324 */ - 0xAE52_8948_E86F_F3F4, /* 325 */ - 0x53DB_D7F2_86A3_F8F8, /* 326 */ - 0x16CA_DCE7_4CFC_1063, /* 327 */ - 0x005C_19BD_FA52_C6DD, /* 328 */ - 0x6886_8F5D_64D4_6AD3, /* 329 */ - 0x3A9D_512C_CF1E_186A, /* 330 */ - 0x367E_62C2_3856_60AE, /* 331 */ - 0xE359_E7EA_77DC_B1D7, /* 332 */ - 0x526C_0773_749A_BE6E, /* 333 */ - 0x735A_E5F9_D09F_734B, /* 334 */ - 0x493F_C7CC_8A55_8BA8, /* 335 */ - 0xB0B9_C153_3041_AB45, /* 336 */ - 0x3219_58BA_470A_59BD, /* 337 */ - 0x852D_B00B_5F46_C393, /* 338 */ - 0x9120_9B2B_D336_B0E5, /* 339 */ - 0x6E60_4F7D_659E_F19F, /* 340 */ - 0xB99A_8AE2_782C_CB24, /* 341 */ - 0xCCF5_2AB6_C814_C4C7, /* 342 */ - 0x4727_D9AF_BE11_727B, /* 343 */ - 0x7E95_0D0C_0121_B34D, /* 344 */ - 0x756F_4356_70AD_471F, /* 345 */ - 0xF5AD_D442_615A_6849, /* 346 */ - 0x4E87_E099_80B9_957A, /* 347 */ - 0x2ACF_A1DF_50AE_E355, /* 348 */ - 0xD898_263A_FD2F_D556, /* 349 */ - 0xC8F4_924D_D80C_8FD6, /* 350 */ - 0xCF99_CA3D_754A_173A, /* 351 */ - 0xFE47_7BAC_AF91_BF3C, /* 352 */ - 0xED53_71F6_D690_C12D, /* 353 */ - 0x831A_5C28_5E68_7094, /* 354 */ - 0xC5D3_C90A_3708_A0A4, /* 355 */ - 0x0F7F_9037_17D0_6580, /* 356 */ - 0x19F9_BB13_B8FD_F27F, /* 357 */ - 0xB1BD_6F1B_4D50_2843, /* 358 */ - 0x1C76_1BA3_8FFF_4012, /* 359 */ - 0x0D15_30C4_E2E2_1F3B, /* 360 */ - 0x8943_CE69_A737_2C8A, /* 361 */ - 0xE518_4E11_FEB5_CE66, /* 362 */ - 0x618B_DB80_BD73_6621, /* 363 */ - 0x7D29_BAD6_8B57_4D0B, /* 364 */ - 0x81BB_613E_25E6_FE5B, /* 365 */ - 0x071C_9C10_BC07_913F, /* 366 */ - 0xC7BE_EB79_09AC_2D97, /* 367 */ - 0xC3E5_8D35_3BC5_D757, /* 368 */ - 0xEB01_7892_F38F_61E8, /* 369 */ - 0xD4EF_FB9C_9B1C_C21A, /* 370 */ - 0x9972_7D26_F494_F7AB, /* 371 */ - 0xA3E0_63A2_956B_3E03, /* 372 */ - 0x9D4A_8B9A_4AA0_9C30, /* 373 */ - 0x3F6A_B7D5_0009_0FB4, /* 374 */ - 0x9CC0_F2A0_5726_8AC0, /* 375 */ - 0x3DEE_9D2D_EDBF_42D1, /* 376 */ - 0x330F_49C8_7960_A972, /* 377 */ - 0xC6B2_7202_8742_1B41, /* 378 */ - 0x0AC5_9EC0_7C00_369C, /* 379 */ - 0xEF4E_AC49_CB35_3425, /* 380 */ - 0xF450_244E_EF01_29D8, /* 381 */ - 0x8ACC_46E5_CAF4_DEB6, /* 382 */ - 0x2FFE_AB63_9892_63F7, /* 383 */ - 0x8F7C_B9FE_5D7A_4578, /* 384 */ - 0x5BD8_F764_4E63_4635, /* 385 */ - 0x427A_7315_BF2D_C900, /* 386 */ - 0x17D0_C4AA_2125_261C, /* 387 */ - 0x3992_486C_9351_8E50, /* 388 */ - 0xB4CB_FEE0_A2D7_D4C3, /* 389 */ - 0x7C75_D620_2C5D_DD8D, /* 390 */ - 0xDBC2_95D8_E35B_6C61, /* 391 */ - 0x60B3_69D3_0203_2B19, /* 392 */ - 0xCE42_685F_DCE4_4132, /* 393 */ - 0x06F3_DDB9_DDF6_5610, /* 394 */ - 0x8EA4_D21D_B5E1_48F0, /* 395 */ - 0x20B0_FCE6_2FCD_496F, /* 396 */ - 0x2C1B_9123_58B0_EE31, /* 397 */ - 0xB283_17B8_18F5_A308, /* 398 */ - 0xA89C_1E18_9CA6_D2CF, /* 399 */ - 0x0C6B_1857_6AAA_DBC8, /* 400 */ - 0xB65D_EAA9_1299_FAE3, /* 401 */ - 0xFB2B_794B_7F10_27E7, /* 402 */ - 0x04E4_317F_443B_5BEB, /* 403 */ - 0x4B85_2D32_5939_D0A6, /* 404 */ - 0xD5AE_6BEE_FB20_7FFC, /* 405 */ - 0x3096_82B2_81C7_D374, /* 406 */ - 0xBAE3_09A1_94C3_B475, /* 407 */ - 0x8CC3_F97B_13B4_9F05, /* 408 */ - 0x98A9_422F_F829_3967, /* 409 */ - 0x244B_16B0_1076_FF7C, /* 410 */ - 0xF8BF_571C_663D_67EE, /* 411 */ - 0x1F0D_6758_EEE3_0DA1, /* 412 */ - 0xC9B6_11D9_7ADE_B9B7, /* 413 */ - 0xB7AF_D588_7B6C_57A2, /* 414 */ - 0x6290_AE84_6B98_4FE1, /* 415 */ - 0x94DF_4CDE_ACC1_A5FD, /* 416 */ - 0x058A_5BD1_C548_3AFF, /* 417 */ - 0x6316_6CC1_42BA_3C37, /* 418 */ - 0x8DB8_526E_B2F7_6F40, /* 419 */ - 0xE108_8003_6F0D_6D4E, /* 420 */ - 0x9E05_23C9_971D_311D, /* 421 */ - 0x45EC_2824_CC7C_D691, /* 422 */ - 0x575B_8359_E623_82C9, /* 423 */ - 0xFA9E_400D_C488_9995, /* 424 */ - 0xD182_3ECB_4572_1568, /* 425 */ - 0xDAFD_983B_8206_082F, /* 426 */ - 0xAA7D_2908_2386_A8CB, /* 427 */ - 0x269F_CD44_03B8_7588, /* 428 */ - 0x1B91_F5F7_28BD_D1E0, /* 429 */ - 0xE466_9F39_0402_01F6, /* 430 */ - 0x7A1D_7C21_8CF0_4ADE, /* 431 */ - 0x6562_3C29_D79C_E5CE, /* 432 */ - 0x2368_4490_96C0_0BB1, /* 433 */ - 0xAB9B_F187_9DA5_03BA, /* 434 */ - 0xBC23_ECB1_A458_058E, /* 435 */ - 0x9A58_DF01_BB40_1ECC, /* 436 */ - 0xA070_E868_A85F_143D, /* 437 */ - 0x4FF1_8830_7DF2_239E, /* 438 */ - 0x14D5_65B4_1A64_1183, /* 439 */ - 0xEE13_3374_5270_1602, /* 440 */ - 0x950E_3DCF_3F28_5E09, /* 441 */ - 0x5993_0254_B9C8_0953, /* 442 */ - 0x3BF2_9940_8930_DA6D, /* 443 */ - 0xA955_943F_5369_1387, /* 444 */ - 0xA15E_DECA_A9CB_8784, /* 445 */ - 0x2914_2127_352B_E9A0, /* 446 */ - 0x76F0_371F_FF4E_7AFB, /* 447 */ - 0x0239_F450_274F_2228, /* 448 */ - 0xBB07_3AF0_1D5E_868B, /* 449 */ - 0xBFC8_0571_C10E_96C1, /* 450 */ - 0xD267_0885_6822_2E23, /* 451 */ - 0x9671_A3D4_8E80_B5B0, /* 452 */ - 0x55B5_D38A_E193_BB81, /* 453 */ - 0x693A_E2D0_A18B_04B8, /* 454 */ - 0x5C48_B4EC_ADD5_335F, /* 455 */ - 0xFD74_3B19_4916_A1CA, /* 456 */ - 0x2577_0181_34BE_98C4, /* 457 */ - 0xE779_87E8_3C54_A4AD, /* 458 */ - 0x28E1_1014_DA33_E1B9, /* 459 */ - 0x270C_C59E_226A_A213, /* 460 */ - 0x7149_5F75_6D1A_5F60, /* 461 */ - 0x9BE8_53FB_60AF_EF77, /* 462 */ - 0xADC7_86A7_F744_3DBF, /* 463 */ - 0x0904_4561_73B2_9A82, /* 464 */ - 0x58BC_7A66_C232_BD5E, /* 465 */ - 0xF306_558C_673A_C8B2, /* 466 */ - 0x41F6_39C6_B6C9_772A, /* 467 */ - 0x216D_EFE9_9FDA_35DA, /* 468 */ - 0x1164_0CC7_1C7B_E615, /* 469 */ - 0x93C4_3694_565C_5527, /* 470 */ - 0xEA03_8E62_4677_7839, /* 471 */ - 0xF9AB_F3CE_5A3E_2469, /* 472 */ - 0x741E_768D_0FD3_12D2, /* 473 */ - 0x0144_B883_CED6_52C6, /* 474 */ - 0xC20B_5A5B_A33F_8552, /* 475 */ - 0x1AE6_9633_C343_5A9D, /* 476 */ - 0x97A2_8CA4_088C_FDEC, /* 477 */ - 0x8824_A43C_1E96_F420, /* 478 */ - 0x3761_2FA6_6EEE_A746, /* 479 */ - 0x6B4C_B165_F9CF_0E5A, /* 480 */ - 0x43AA_1C06_A0AB_FB4A, /* 481 */ - 0x7F4D_C26F_F162_796B, /* 482 */ - 0x6CBA_CC8E_54ED_9B0F, /* 483 */ - 0xA6B7_FFEF_D2BB_253E, /* 484 */ - 0x2E25_BC95_B0A2_9D4F, /* 485 */ - 0x86D6_A58B_DEF1_388C, /* 486 */ - 0xDED7_4AC5_76B6_F054, /* 487 */ - 0x8030_BDBC_2B45_805D, /* 488 */ - 0x3C81_AF70_E94D_9289, /* 489 */ - 0x3EFF_6DDA_9E31_00DB, /* 490 */ - 0xB38D_C39F_DFCC_8847, /* 491 */ - 0x1238_8552_8D17_B87E, /* 492 */ - 0xF2DA_0ED2_40B1_B642, /* 493 */ - 0x44CE_FADC_D54B_F9A9, /* 494 */ - 0x1312_200E_433C_7EE6, /* 495 */ - 0x9FFC_C84F_3A78_C748, /* 496 */ - 0xF0CD_1F72_2485_76BB, /* 497 */ - 0xEC69_7405_3638_CFE4, /* 498 */ - 0x2BA7_B67C_0CEC_4E4C, /* 499 */ - 0xAC2F_4DF3_E5CE_32ED, /* 500 */ - 0xCB33_D143_26EA_4C11, /* 501 */ - 0xA4E9_044C_C77E_58BC, /* 502 */ - 0x5F51_3293_D934_FCEF, /* 503 */ - 0x5DC9_6455_06E5_5444, /* 504 */ - 0x50DE_418F_317D_E40A, /* 505 */ - 0x388C_B31A_69DD_E259, /* 506 */ - 0x2DB4_A834_5582_0A86, /* 507 */ - 0x9010_A91E_8471_1AE9, /* 508 */ - 0x4DF7_F0B7_B149_8371, /* 509 */ - 0xD62A_2EAB_C097_7179, /* 510 */ - 0x22FA_C097_AA8D_5C0E, /* 511 */ -]; -static T3: [u64; 256] = [ - 0xF49F_CC2F_F1DA_F39B, /* 512 */ - 0x487F_D5C6_6FF2_9281, /* 513 */ - 0xE8A3_0667_FCDC_A83F, /* 514 */ - 0x2C9B_4BE3_D2FC_CE63, /* 515 */ - 0xDA3F_F74B_93FB_BBC2, /* 516 */ - 0x2FA1_65D2_FE70_BA66, /* 517 */ - 0xA103_E279_970E_93D4, /* 518 */ - 0xBECD_EC77_B0E4_5E71, /* 519 */ - 0xCFB4_1E72_3985_E497, /* 520 */ - 0xB70A_AA02_5EF7_5017, /* 521 */ - 0xD423_09F0_3840_B8E0, /* 522 */ - 0x8EFC_1AD0_3589_8579, /* 523 */ - 0x96C6_920B_E2B2_ABC5, /* 524 */ - 0x66AF_4163_375A_9172, /* 525 */ - 0x2174_ABDC_CA71_27FB, /* 526 */ - 0xB33C_CEA6_4A72_FF41, /* 527 */ - 0xF04A_4933_0830_66A5, /* 528 */ - 0x8D97_0ACD_D728_9AF5, /* 529 */ - 0x8F96_E8E0_31C8_C25E, /* 530 */ - 0xF3FE_C022_7687_5D47, /* 531 */ - 0xEC7B_F310_0561_90DD, /* 532 */ - 0xF5AD_B0AE_BB0F_1491, /* 533 */ - 0x9B50_F885_0FD5_8892, /* 534 */ - 0x4975_4883_58B7_4DE8, /* 535 */ - 0xA335_4FF6_9153_1C61, /* 536 */ - 0x0702_BBE4_81D2_C6EE, /* 537 */ - 0x89FB_2405_7DED_ED98, /* 538 */ - 0xAC30_7513_8596_E902, /* 539 */ - 0x1D2D_3580_1727_72ED, /* 540 */ - 0xEB73_8FC2_8E6B_C30D, /* 541 */ - 0x5854_EF8F_6304_4326, /* 542 */ - 0x9E5C_5232_5ADD_3BBE, /* 543 */ - 0x90AA_53CF_325C_4623, /* 544 */ - 0xC1D2_4D51_349D_D067, /* 545 */ - 0x2051_CFEE_A69E_A624, /* 546 */ - 0x1322_0F0A_862E_7E4F, /* 547 */ - 0xCE39_3994_04E0_4864, /* 548 */ - 0xD9C4_2CA4_7086_FCB7, /* 549 */ - 0x685A_D223_8A03_E7CC, /* 550 */ - 0x0664_84B2_AB2F_F1DB, /* 551 */ - 0xFE9D_5D70_EFBF_79EC, /* 552 */ - 0x5B13_B9DD_9C48_1854, /* 553 */ - 0x15F0_D475_ED15_09AD, /* 554 */ - 0x0BEB_CD06_0EC7_9851, /* 555 */ - 0xD58C_6791_183A_B7F8, /* 556 */ - 0xD118_7C50_52F3_EEE4, /* 557 */ - 0xC95D_1192_E54E_82FF, /* 558 */ - 0x86EE_A14C_B9AC_6CA2, /* 559 */ - 0x3485_BEB1_5367_7D5D, /* 560 */ - 0xDD19_1D78_1F8C_492A, /* 561 */ - 0xF608_66BA_A784_EBF9, /* 562 */ - 0x518F_643B_A2D0_8C74, /* 563 */ - 0x8852_E956_E108_7C22, /* 564 */ - 0xA768_CB8D_C410_AE8D, /* 565 */ - 0x3804_7726_BFEC_8E1A, /* 566 */ - 0xA677_38B4_CD3B_45AA, /* 567 */ - 0xAD16_691C_EC0D_DE19, /* 568 */ - 0xC6D4_3193_8046_2E07, /* 569 */ - 0xC5A5_876D_0BA6_1938, /* 570 */ - 0x16B9_FA1F_A58F_D840, /* 571 */ - 0x188A_B117_3CA7_4F18, /* 572 */ - 0xABDA_2F98_C99C_021F, /* 573 */ - 0x3E05_80AB_134A_E816, /* 574 */ - 0x5F3B_05B7_7364_5ABB, /* 575 */ - 0x2501_A2BE_5575_F2F6, /* 576 */ - 0x1B2F_7400_4E7E_8BA9, /* 577 */ - 0x1CD7_5803_71E8_D953, /* 578 */ - 0x7F6E_D895_6276_4E30, /* 579 */ - 0xB159_26FF_596F_003D, /* 580 */ - 0x9F65_293D_A8C5_D6B9, /* 581 */ - 0x6ECE_F04D_D690_F84C, /* 582 */ - 0x4782_275F_FF33_AF88, /* 583 */ - 0xE414_3308_3F82_0801, /* 584 */ - 0xFD0D_FE40_9A1A_F9B5, /* 585 */ - 0x4325_A334_2CDB_396B, /* 586 */ - 0x8AE7_7E62_B301_B252, /* 587 */ - 0xC36F_9E9F_6655_615A, /* 588 */ - 0x8545_5A2D_92D3_2C09, /* 589 */ - 0xF2C7_DEA9_4947_7485, /* 590 */ - 0x63CF_B4C1_33A3_9EBA, /* 591 */ - 0x83B0_40CC_6EBC_5462, /* 592 */ - 0x3B94_54C8_FDB3_26B0, /* 593 */ - 0x56F5_6A9E_87FF_D78C, /* 594 */ - 0x2DC2_940D_99F4_2BC6, /* 595 */ - 0x98F7_DF09_6B09_6E2D, /* 596 */ - 0x19A6_E01E_3AD8_52BF, /* 597 */ - 0x42A9_9CCB_DBD4_B40B, /* 598 */ - 0xA599_98AF_45E9_C559, /* 599 */ - 0x3662_95E8_07D9_3186, /* 600 */ - 0x6B48_181B_FAA1_F773, /* 601 */ - 0x1FEC_57E2_157A_0A1D, /* 602 */ - 0x4667_446A_F620_1AD5, /* 603 */ - 0xE615_EBCA_CFB0_F075, /* 604 */ - 0xB8F3_1F4F_6829_0778, /* 605 */ - 0x2271_3ED6_CE22_D11E, /* 606 */ - 0x3057_C1A7_2EC3_C93B, /* 607 */ - 0xCB46_ACC3_7C3F_1F2F, /* 608 */ - 0xDBB8_93FD_02AA_F50E, /* 609 */ - 0x331F_D92E_600B_9FCF, /* 610 */ - 0xA498_F961_48EA_3AD6, /* 611 */ - 0xA8D8_426E_8B6A_83EA, /* 612 */ - 0xA089_B274_B773_5CDC, /* 613 */ - 0x87F6_B373_1E52_4A11, /* 614 */ - 0x1188_08E5_CBC9_6749, /* 615 */ - 0x9906_E4C7_B19B_D394, /* 616 */ - 0xAFED_7F7E_9B24_A20C, /* 617 */ - 0x6509_EADE_EB36_44A7, /* 618 */ - 0x6C1E_F1D3_E8EF_0EDE, /* 619 */ - 0xB9C9_7D43_E979_8FB4, /* 620 */ - 0xA2F2_D784_740C_28A3, /* 621 */ - 0x7B84_9647_6197_566F, /* 622 */ - 0x7A5B_E3E6_B65F_069D, /* 623 */ - 0xF963_30ED_78BE_6F10, /* 624 */ - 0xEEE6_0DE7_7A07_6A15, /* 625 */ - 0x2B4B_EE4A_A08B_9BD0, /* 626 */ - 0x6A56_A63E_C7B8_894E, /* 627 */ - 0x0212_1359_BA34_FEF4, /* 628 */ - 0x4CBF_99F8_2837_03FC, /* 629 */ - 0x3980_7135_0CAF_30C8, /* 630 */ - 0xD0A7_7A89_F017_687A, /* 631 */ - 0xF1C1_A9EB_9E42_3569, /* 632 */ - 0x8C79_7628_2DEE_8199, /* 633 */ - 0x5D17_37A5_DD1F_7ABD, /* 634 */ - 0x4F53_433C_09A9_FA80, /* 635 */ - 0xFA8B_0C53_DF7C_A1D9, /* 636 */ - 0x3FD9_DCBC_886C_CB77, /* 637 */ - 0xC040_917C_A91B_4720, /* 638 */ - 0x7DD0_0142_F9D1_DCDF, /* 639 */ - 0x8476_FC1D_4F38_7B58, /* 640 */ - 0x23F8_E7C5_F331_6503, /* 641 */ - 0x032A_2244_E7E3_7339, /* 642 */ - 0x5C87_A5D7_50F5_A74B, /* 643 */ - 0x082B_4CC4_3698_992E, /* 644 */ - 0xDF91_7BEC_B858_F63C, /* 645 */ - 0x3270_B8FC_5BF8_6DDA, /* 646 */ - 0x10AE_72BB_29B5_DD76, /* 647 */ - 0x576A_C94E_7700_362B, /* 648 */ - 0x1AD1_12DA_C61E_FB8F, /* 649 */ - 0x691B_C30E_C5FA_A427, /* 650 */ - 0xFF24_6311_CC32_7143, /* 651 */ - 0x3142_368E_30E5_3206, /* 652 */ - 0x7138_0E31_E02C_A396, /* 653 */ - 0x958D_5C96_0AAD_76F1, /* 654 */ - 0xF8D6_F430_C16D_A536, /* 655 */ - 0xC8FF_D13F_1BE7_E1D2, /* 656 */ - 0x7578_AE66_004D_DBE1, /* 657 */ - 0x0583_3F01_067B_E646, /* 658 */ - 0xBB34_B5AD_3BFE_586D, /* 659 */ - 0x095F_34C9_A12B_97F0, /* 660 */ - 0x247A_B645_25D6_0CA8, /* 661 */ - 0xDCDB_C6F3_0174_77D1, /* 662 */ - 0x4A2E_14D4_DECA_D24D, /* 663 */ - 0xBDB5_E6D9_BE0A_1EEB, /* 664 */ - 0x2A7E_70F7_7943_01AB, /* 665 */ - 0xDEF4_2D8A_2705_40FD, /* 666 */ - 0x0107_8EC0_A34C_22C1, /* 667 */ - 0xE5DE_511A_F4C1_6387, /* 668 */ - 0x7EBB_3A52_BD9A_330A, /* 669 */ - 0x7769_7857_AA7D_6435, /* 670 */ - 0x004E_8316_03AE_4C32, /* 671 */ - 0xE7A2_1020_AD78_E312, /* 672 */ - 0x9D41_A70C_6AB4_20F2, /* 673 */ - 0x28E0_6C18_EA11_41E6, /* 674 */ - 0xD2B2_8CBD_984F_6B28, /* 675 */ - 0x26B7_5F6C_446E_9D83, /* 676 */ - 0xBA47_568C_4D41_8D7F, /* 677 */ - 0xD80B_ADBF_E618_3D8E, /* 678 */ - 0x0E20_6D7F_5F16_6044, /* 679 */ - 0xE258_A439_11CB_CA3E, /* 680 */ - 0x723A_1746_B21D_C0BC, /* 681 */ - 0xC7CA_A854_F5D7_CDD3, /* 682 */ - 0x7CAC_3288_3D26_1D9C, /* 683 */ - 0x7690_C264_23BA_942C, /* 684 */ - 0x17E5_5524_4780_42B8, /* 685 */ - 0xE0BE_4776_56A2_389F, /* 686 */ - 0x4D28_9B5E_67AB_2DA0, /* 687 */ - 0x4486_2B9C_8FBB_FD31, /* 688 */ - 0xB47C_C804_9D14_1365, /* 689 */ - 0x822C_1B36_2B91_C793, /* 690 */ - 0x4EB1_4655_FB13_DFD8, /* 691 */ - 0x1ECB_BA07_14E2_A97B, /* 692 */ - 0x6143_459D_5CDE_5F14, /* 693 */ - 0x53A8_FBF1_D5F0_AC89, /* 694 */ - 0x97EA_04D8_1C5E_5B00, /* 695 */ - 0x6221_81A8_D4FD_B3F3, /* 696 */ - 0xE9BC_D341_572A_1208, /* 697 */ - 0x1411_2586_43CC_E58A, /* 698 */ - 0x9144_C5FE_A4C6_E0A4, /* 699 */ - 0x0D33_D065_65CF_620F, /* 700 */ - 0x54A4_8D48_9F21_9CA1, /* 701 */ - 0xC43E_5EAC_6D63_C821, /* 702 */ - 0xA972_8B3A_7277_0DAF, /* 703 */ - 0xD793_4E7B_20DF_87EF, /* 704 */ - 0xE355_03B6_1A3E_86E5, /* 705 */ - 0xCAE3_21FB_C819_D504, /* 706 */ - 0x129A_50B3_AC60_BFA6, /* 707 */ - 0xCD5E_68EA_7E9F_B6C3, /* 708 */ - 0xB01C_9019_9483_B1C7, /* 709 */ - 0x3DE9_3CD5_C295_376C, /* 710 */ - 0xAED5_2EDF_2AB9_AD13, /* 711 */ - 0x2E60_F512_C0A0_7884, /* 712 */ - 0xBC3D_86A3_E362_10C9, /* 713 */ - 0x3526_9D9B_1639_51CE, /* 714 */ - 0x0C7D_6E2A_D0CD_B5FA, /* 715 */ - 0x59E8_6297_D87F_5733, /* 716 */ - 0x298E_F221_898D_B0E7, /* 717 */ - 0x5500_0029_D1A5_AA7E, /* 718 */ - 0x8BC0_8AE1_B506_1B45, /* 719 */ - 0xC2C3_1C2B_6C92_703A, /* 720 */ - 0x94CC_596B_AF25_EF42, /* 721 */ - 0x0A1D_73DB_2254_0456, /* 722 */ - 0x04B6_A0F9_D9C4_179A, /* 723 */ - 0xEFFD_AFA2_AE3D_3C60, /* 724 */ - 0xF7C8_075B_B494_96C4, /* 725 */ - 0x9CC5_C714_1D1C_D4E3, /* 726 */ - 0x78BD_1638_218E_5534, /* 727 */ - 0xB2F1_1568_F850_246A, /* 728 */ - 0xEDFA_BCFA_9502_BC29, /* 729 */ - 0x796C_E5F2_DA23_051B, /* 730 */ - 0xAAE1_28B0_DC93_537C, /* 731 */ - 0x3A49_3DA0_EE4B_29AE, /* 732 */ - 0xB5DF_6B2C_4168_95D7, /* 733 */ - 0xFCAB_BD25_122D_7F37, /* 734 */ - 0x7081_0B58_105D_C4B1, /* 735 */ - 0xE10F_DD37_F788_2A90, /* 736 */ - 0x524D_CAB5_518A_3F5C, /* 737 */ - 0x3C9E_8587_8451_255B, /* 738 */ - 0x4029_8281_19BD_34E2, /* 739 */ - 0x74A0_5B6F_5D3C_ECCB, /* 740 */ - 0xB610_0215_42E1_3ECA, /* 741 */ - 0x0FF9_79D1_2F59_E2AC, /* 742 */ - 0x6037_DA27_E4F9_CC50, /* 743 */ - 0x5E92_975A_0DF1_847D, /* 744 */ - 0xD66D_E190_D3E6_23FE, /* 745 */ - 0x5032_D6B8_7B56_8048, /* 746 */ - 0x9A36_B7CE_8235_216E, /* 747 */ - 0x8027_2A7A_24F6_4B4A, /* 748 */ - 0x93EF_ED8B_8C69_16F7, /* 749 */ - 0x37DD_BFF4_4CCE_1555, /* 750 */ - 0x4B95_DB5D_4B99_BD25, /* 751 */ - 0x92D3_FDA1_6981_2FC0, /* 752 */ - 0xFB1A_4A9A_9066_0BB6, /* 753 */ - 0x730C_1969_46A4_B9B2, /* 754 */ - 0x81E2_89AA_7F49_DA68, /* 755 */ - 0x6466_9A0F_83B1_A05F, /* 756 */ - 0x27B3_FF7D_9644_F48B, /* 757 */ - 0xCC6B_615C_8DB6_75B3, /* 758 */ - 0x674F_20B9_BCEB_BE95, /* 759 */ - 0x6F31_2382_7565_5982, /* 760 */ - 0x5AE4_8871_3E45_CF05, /* 761 */ - 0xBF61_9F99_54C2_1157, /* 762 */ - 0xEABA_C460_40A8_EAE9, /* 763 */ - 0x454C_6FE9_F2C0_C1CD, /* 764 */ - 0x419C_F649_6412_691C, /* 765 */ - 0xD3DC_3BEF_265B_0F70, /* 766 */ - 0x6D0E_60F5_C357_8A9E, /* 767 */ -]; -static T4: [u64; 256] = [ - 0x5B0E_6085_2632_3C55, /* 768 */ - 0x1A46_C1A9_FA1B_59F5, /* 769 */ - 0xA9E2_45A1_7C4C_8FFA, /* 770 */ - 0x65CA_5159_DB29_55D7, /* 771 */ - 0x05DB_0A76_CE35_AFC2, /* 772 */ - 0x81EA_C77E_A911_3D45, /* 773 */ - 0x528E_F88A_B6AC_0A0D, /* 774 */ - 0xA09E_A253_597B_E3FF, /* 775 */ - 0x430D_DFB3_AC48_CD56, /* 776 */ - 0xC4B3_A67A_F45C_E46F, /* 777 */ - 0x4ECE_CFD8_FBE2_D05E, /* 778 */ - 0x3EF5_6F10_B399_35F0, /* 779 */ - 0x0B22_D682_9CD6_19C6, /* 780 */ - 0x17FD_460A_74DF_2069, /* 781 */ - 0x6CF8_CC8E_8510_ED40, /* 782 */ - 0xD6C8_24BF_3A6E_CAA7, /* 783 */ - 0x6124_3D58_1A81_7049, /* 784 */ - 0x048B_ACB6_BBC1_63A2, /* 785 */ - 0xD9A3_8AC2_7D44_CC32, /* 786 */ - 0x7FDD_FF5B_AAF4_10AB, /* 787 */ - 0xAD6D_495A_A804_824B, /* 788 */ - 0xE1A6_A74F_2D8C_9F94, /* 789 */ - 0xD4F7_8512_35DE_E8E3, /* 790 */ - 0xFD4B_7F88_6540_D893, /* 791 */ - 0x247C_2004_2AA4_BFDA, /* 792 */ - 0x096E_A1C5_17D1_327C, /* 793 */ - 0xD569_66B4_361A_6685, /* 794 */ - 0x277D_A5C3_1221_057D, /* 795 */ - 0x94D5_9893_A43A_CFF7, /* 796 */ - 0x64F0_C51C_CDC0_2281, /* 797 */ - 0x3D33_BCC4_FF61_89DB, /* 798 */ - 0xE005_CB18_4CE6_6AF1, /* 799 */ - 0xFF5C_CD1D_1DB9_9BEA, /* 800 */ - 0xB0B8_54A7_FE42_980F, /* 801 */ - 0x7BD4_6A6A_718D_4B9F, /* 802 */ - 0xD10F_A8CC_22A5_FD8C, /* 803 */ - 0xD314_8495_2BE4_BD31, /* 804 */ - 0xC7FA_975F_CB24_3847, /* 805 */ - 0x4886_ED1E_5846_C407, /* 806 */ - 0x28CD_DB79_1EB7_0B04, /* 807 */ - 0xC2B0_0BE2_F573_417F, /* 808 */ - 0x5C95_9045_2180_F877, /* 809 */ - 0x7A6B_DDFF_F370_EB00, /* 810 */ - 0xCE50_9E38_D6D9_D6A4, /* 811 */ - 0xEBEB_0F00_647F_A702, /* 812 */ - 0x1DCC_06CF_7660_6F06, /* 813 */ - 0xE4D9_F28B_A286_FF0A, /* 814 */ - 0xD85A_305D_C918_C262, /* 815 */ - 0x475B_1D87_3222_5F54, /* 816 */ - 0x2D4F_B516_68CC_B5FE, /* 817 */ - 0xA679_B9D9_D72B_BA20, /* 818 */ - 0x5384_1C0D_912D_43A5, /* 819 */ - 0x3B7E_AA48_BF12_A4E8, /* 820 */ - 0x781E_0E47_F22F_1DDF, /* 821 */ - 0xEFF2_0CE6_0AB5_0973, /* 822 */ - 0x20D2_61D1_9DFF_B742, /* 823 */ - 0x16A1_2B03_062A_2E39, /* 824 */ - 0x1960_EB22_3965_0495, /* 825 */ - 0x251C_16FE_D50E_B8B8, /* 826 */ - 0x9AC0_C330_F826_016E, /* 827 */ - 0xED15_2665_953E_7671, /* 828 */ - 0x02D6_3194_A636_9570, /* 829 */ - 0x5074_F083_94B1_C987, /* 830 */ - 0x70BA_598C_90B2_5CE1, /* 831 */ - 0x794A_1581_0B97_42F6, /* 832 */ - 0x0D59_25E9_FCAF_8C6C, /* 833 */ - 0x3067_716C_D868_744E, /* 834 */ - 0x910A_B077_E8D7_731B, /* 835 */ - 0x6A61_BBDB_5AC4_2F61, /* 836 */ - 0x9351_3EFB_F085_1567, /* 837 */ - 0xF494_724B_9E83_E9D5, /* 838 */ - 0xE887_E198_5C09_648D, /* 839 */ - 0x34B1_D3C6_7537_0CFD, /* 840 */ - 0xDC35_E433_BC0D_255D, /* 841 */ - 0xD0AA_B842_3413_1BE0, /* 842 */ - 0x0804_2A50_B48B_7EAF, /* 843 */ - 0x9997_C4EE_44A3_AB35, /* 844 */ - 0x829A_7B49_2017_99D0, /* 845 */ - 0x263B_8307_B7C5_4441, /* 846 */ - 0x752F_95F4_FD6A_6CA6, /* 847 */ - 0x9272_1740_2C08_C6E5, /* 848 */ - 0x2A8A_B754_A795_D9EE, /* 849 */ - 0xA442_F755_2F72_943D, /* 850 */ - 0x2C31_334E_1978_1208, /* 851 */ - 0x4FA9_8D7C_EAEE_6291, /* 852 */ - 0x55C3_862F_665D_B309, /* 853 */ - 0xBD06_1017_5D53_B1F3, /* 854 */ - 0x46FE_6CB8_4041_3F27, /* 855 */ - 0x3FE0_3792_DF0C_FA59, /* 856 */ - 0xCFE7_0037_2EB8_5E8F, /* 857 */ - 0xA7BE_29E7_ADBC_E118, /* 858 */ - 0xE544_EE5C_DE84_31DD, /* 859 */ - 0x8A78_1B1B_41F1_873E, /* 860 */ - 0xA5C9_4C78_A0D2_F0E7, /* 861 */ - 0x3941_2E28_77B6_0728, /* 862 */ - 0xA126_5EF3_AFC9_A62C, /* 863 */ - 0xBCC2_770C_6A25_06C5, /* 864 */ - 0x3AB6_6DD5_DCE1_CE12, /* 865 */ - 0xE654_99D0_4A67_5B37, /* 866 */ - 0x7D8F_5234_81BF_D216, /* 867 */ - 0x0F6F_64FC_EC15_F389, /* 868 */ - 0x74EF_BE61_8B5B_13C8, /* 869 */ - 0xACDC_82B7_1427_3E1D, /* 870 */ - 0xDD40_BFE0_0319_9D17, /* 871 */ - 0x37E9_9257_E7E0_61F8, /* 872 */ - 0xFA52_6269_0477_5AAA, /* 873 */ - 0x8BBB_F63A_463D_56F9, /* 874 */ - 0xF001_3F15_43A2_6E64, /* 875 */ - 0xA830_7E9F_879E_C898, /* 876 */ - 0xCC4C_27A4_1501_77CC, /* 877 */ - 0x1B43_2F2C_CA1D_3348, /* 878 */ - 0xDE1D_1F8F_9F6F_A013, /* 879 */ - 0x6066_02A0_47A7_DDD6, /* 880 */ - 0xD237_AB64_CC1C_B2C7, /* 881 */ - 0x9B93_8E72_25FC_D1D3, /* 882 */ - 0xEC4E_0370_8E0F_F476, /* 883 */ - 0xFEB2_FBDA_3D03_C12D, /* 884 */ - 0xAE0B_CED2_EE43_889A, /* 885 */ - 0x22CB_8923_EBFB_4F43, /* 886 */ - 0x6936_0D01_3CF7_396D, /* 887 */ - 0x855E_3602_D2D4_E022, /* 888 */ - 0x0738_05BA_D01F_784C, /* 889 */ - 0x33E1_7A13_3852_F546, /* 890 */ - 0xDF48_7405_8AC7_B638, /* 891 */ - 0xBA92_B29C_678A_A14A, /* 892 */ - 0x0CE8_9FC7_6CFA_ADCD, /* 893 */ - 0x5F9D_4E09_0833_9E34, /* 894 */ - 0xF1AF_E929_1F59_23B9, /* 895 */ - 0x6E34_80F6_0F4A_265F, /* 896 */ - 0xEEBF_3A2A_B29B_841C, /* 897 */ - 0xE219_38A8_8F91_B4AD, /* 898 */ - 0x57DF_EFF8_45C6_D3C3, /* 899 */ - 0x2F00_6B0B_F62C_AAF2, /* 900 */ - 0x62F4_79EF_6F75_EE78, /* 901 */ - 0x11A5_5AD4_1C89_16A9, /* 902 */ - 0xF229_D290_84FE_D453, /* 903 */ - 0x42F1_C27B_16B0_00E6, /* 904 */ - 0x2B1F_7674_9823_C074, /* 905 */ - 0x4B76_ECA3_C274_5360, /* 906 */ - 0x8C98_F463_B916_91BD, /* 907 */ - 0x14BC_C93C_F1AD_E66A, /* 908 */ - 0x8885_213E_6D45_8397, /* 909 */ - 0x8E17_7DF0_274D_4711, /* 910 */ - 0xB49B_73B5_503F_2951, /* 911 */ - 0x1016_8168_C3F9_6B6B, /* 912 */ - 0x0E3D_963B_63CA_B0AE, /* 913 */ - 0x8DFC_4B56_55A1_DB14, /* 914 */ - 0xF789_F135_6E14_DE5C, /* 915 */ - 0x683E_68AF_4E51_DAC1, /* 916 */ - 0xC9A8_4F9D_8D4B_0FD9, /* 917 */ - 0x3691_E03F_52A0_F9D1, /* 918 */ - 0x5ED8_6E46_E187_8E80, /* 919 */ - 0x3C71_1A0E_99D0_7150, /* 920 */ - 0x5A08_65B2_0C4E_9310, /* 921 */ - 0x56FB_FC1F_E4F0_682E, /* 922 */ - 0xEA8D_5DE3_105E_DF9B, /* 923 */ - 0x71AB_FDB1_2379_187A, /* 924 */ - 0x2EB9_9DE1_BEE7_7B9C, /* 925 */ - 0x21EC_C0EA_33CF_4523, /* 926 */ - 0x59A4_D752_1805_C7A1, /* 927 */ - 0x3896_F5EB_56AE_7C72, /* 928 */ - 0xAA63_8F3D_B18F_75DC, /* 929 */ - 0x9F39_358D_ABE9_808E, /* 930 */ - 0xB7DE_FA91_C00B_72AC, /* 931 */ - 0x6B55_41FD_6249_2D92, /* 932 */ - 0x6DC6_DEE8_F92E_4D5B, /* 933 */ - 0x353F_57AB_C4BE_EA7E, /* 934 */ - 0x7357_69D6_DA56_90CE, /* 935 */ - 0x0A23_4AA6_4239_1484, /* 936 */ - 0xF6F9_5080_28F8_0D9D, /* 937 */ - 0xB8E3_19A2_7AB3_F215, /* 938 */ - 0x31AD_9C11_5134_1A4D, /* 939 */ - 0x773C_22A5_7BEF_5805, /* 940 */ - 0x45C7_561A_0796_8633, /* 941 */ - 0xF913_DA9E_249D_BE36, /* 942 */ - 0xDA65_2D9B_78A6_4C68, /* 943 */ - 0x4C27_A97F_3BC3_34EF, /* 944 */ - 0x7662_1220_E66B_17F4, /* 945 */ - 0x9677_4389_9ACD_7D0B, /* 946 */ - 0xF3EE_5BCA_E0ED_6782, /* 947 */ - 0x409F_7536_00C8_79FC, /* 948 */ - 0x06D0_9A39_B592_6DB6, /* 949 */ - 0x6F83_AEB0_317A_C588, /* 950 */ - 0x01E6_CA4A_8638_1F21, /* 951 */ - 0x66FF_3462_D19F_3025, /* 952 */ - 0x7220_7C24_DDFD_3BFB, /* 953 */ - 0x4AF6_B6D3_E2EC_E2EB, /* 954 */ - 0x9C99_4DBE_C7EA_08DE, /* 955 */ - 0x49AC_E597_B09A_8BC4, /* 956 */ - 0xB38C_4766_CF07_97BA, /* 957 */ - 0x131B_9373_C57C_2A75, /* 958 */ - 0xB182_2CCE_6193_1E58, /* 959 */ - 0x9D75_55B9_09BA_1C0C, /* 960 */ - 0x127F_AFDD_937D_11D2, /* 961 */ - 0x29DA_3BAD_C66D_92E4, /* 962 */ - 0xA2C1_D571_54C2_ECBC, /* 963 */ - 0x58C5_134D_82F6_FE24, /* 964 */ - 0x1C3A_E351_5B62_274F, /* 965 */ - 0xE907_C82E_01CB_8126, /* 966 */ - 0xF8ED_0919_13E3_7FCB, /* 967 */ - 0x3249_D8F9_C800_46C9, /* 968 */ - 0x80CF_9BED_E388_FB63, /* 969 */ - 0x1881_539A_116C_F19E, /* 970 */ - 0x5103_F3F7_6BD5_2457, /* 971 */ - 0x15B7_E6F5_AE47_F7A8, /* 972 */ - 0xDBD7_C6DE_D47E_9CCF, /* 973 */ - 0x44E5_5C41_0228_BB1A, /* 974 */ - 0xB647_D425_5EDB_4E99, /* 975 */ - 0x5D11_882B_B8AA_FC30, /* 976 */ - 0xF509_8BBB_29D3_212A, /* 977 */ - 0x8FB5_EA14_E902_96B3, /* 978 */ - 0x677B_9421_57DD_025A, /* 979 */ - 0xFB58_E7C0_A390_ACB5, /* 980 */ - 0x89D3_674C_83BD_4A01, /* 981 */ - 0x9E2D_A4DF_4BF3_B93B, /* 982 */ - 0xFCC4_1E32_8CAB_4829, /* 983 */ - 0x03F3_8C96_BA58_2C52, /* 984 */ - 0xCAD1_BDBD_7FD8_5DB2, /* 985 */ - 0xBBB4_42C1_6082_AE83, /* 986 */ - 0xB95F_E86B_A5DA_9AB0, /* 987 */ - 0xB22E_0467_3771_A93F, /* 988 */ - 0x8453_58C9_4931_52D8, /* 989 */ - 0xBE2A_4886_97B4_541E, /* 990 */ - 0x95A2_DC2D_D38E_6966, /* 991 */ - 0xC02C_11AC_923C_852B, /* 992 */ - 0x2388_B199_0DF2_A87B, /* 993 */ - 0x7C80_08FA_1B4F_37BE, /* 994 */ - 0x1F70_D0C8_4D54_E503, /* 995 */ - 0x5490_ADEC_7ECE_57D4, /* 996 */ - 0x002B_3C27_D906_3A3A, /* 997 */ - 0x7EAE_A384_8030_A2BF, /* 998 */ - 0xC602_326D_ED20_03C0, /* 999 */ - 0x83A7_287D_69A9_4086, /* 1000 */ - 0xC57A_5FCB_30F5_7A8A, /* 1001 */ - 0xB568_44E4_79EB_E779, /* 1002 */ - 0xA373_B40F_05DC_BCE9, /* 1003 */ - 0xD71A_786E_8857_0EE2, /* 1004 */ - 0x879C_BACD_BDE8_F6A0, /* 1005 */ - 0x976A_D1BC_C164_A32F, /* 1006 */ - 0xAB21_E25E_9666_D78B, /* 1007 */ - 0x9010_63AA_E5E5_C33C, /* 1008 */ - 0x9818_B344_4869_8D90, /* 1009 */ - 0xE364_87AE_3E1E_8ABB, /* 1010 */ - 0xAFBD_F931_893B_DCB4, /* 1011 */ - 0x6345_A0DC_5FBB_D519, /* 1012 */ - 0x8628_FE26_9B94_65CA, /* 1013 */ - 0x1E5D_0160_3F9C_51EC, /* 1014 */ - 0x4DE4_4006_A150_49B7, /* 1015 */ - 0xBF6C_70E5_F776_CBB1, /* 1016 */ - 0x4112_18F2_EF55_2BED, /* 1017 */ - 0xCB0C_0708_705A_36A3, /* 1018 */ - 0xE74D_1475_4F98_6044, /* 1019 */ - 0xCD56_D943_0EA8_280E, /* 1020 */ - 0xC125_91D7_535F_5065, /* 1021 */ - 0xC832_23F1_720A_EF96, /* 1022 */ - 0xC3A0_396F_7363_A51F, /* 1023 */ -]; +/// Tiger hasher state. +pub type Tiger = CoreWrapper; +/// Tiger2 hasher state. +pub type Tiger2 = CoreWrapper; diff --git a/tiger/src/tables.rs b/tiger/src/tables.rs new file mode 100644 index 000000000..dc6e2c21e --- /dev/null +++ b/tiger/src/tables.rs @@ -0,0 +1,1035 @@ +pub(crate) static T1: [u64; 256] = [ + 0x02AA_B17C_F7E9_0C5E, + 0xAC42_4B03_E243_A8EC, + 0x72CD_5BE3_0DD5_FCD3, + 0x6D01_9B93_F6F9_7F3A, + 0xCD99_78FF_D21F_9193, + 0x7573_A1C9_7080_29E2, + 0xB164_326B_922A_83C3, + 0x4688_3EEE_0491_5870, + 0xEAAC_E305_7103_ECE6, + 0xC541_69B8_08A3_535C, + 0x4CE7_5491_8DDE_C47C, + 0x0AA2_F4DF_DC0D_F40C, + 0x10B7_6F18_A74D_BEFA, + 0xC6CC_B623_5AD1_AB6A, + 0x1372_6121_572F_E2FF, + 0x1A48_8C6F_199D_921E, + 0x4BC9_F9F4_DA00_07CA, + 0x26F5_E6F6_E852_41C7, + 0x8590_79DB_EA59_47B6, + 0x4F18_85C5_C99E_8C92, + 0xD78E_761E_A96F_864B, + 0x8E36_428C_52B5_C17D, + 0x69CF_6827_3730_63C1, + 0xB607_C93D_9BB4_C56E, + 0x7D82_0E76_0E76_B5EA, + 0x645C_9CC6_F07F_DC42, + 0xBF38_A078_2433_42E0, + 0x5F6B_343C_9D2E_7D04, + 0xF2C2_8AEB_600B_0EC6, + 0x6C0E_D85F_7254_BCAC, + 0x7159_2281_A4DB_4FE5, + 0x1967_FA69_CE0F_ED9F, + 0xFD52_93F8_B965_45DB, + 0xC879_E9D7_F2A7_600B, + 0x8602_4892_0193_194E, + 0xA4F9_533B_2D9C_C0B3, + 0x9053_836C_1595_7613, + 0xDB6D_CF8A_FC35_7BF1, + 0x18BE_EA7A_7A37_0F57, + 0x0371_17CA_50B9_9066, + 0x6AB3_0A97_7442_4A35, + 0xF4E9_2F02_E325_249B, + 0x7739_DB07_061C_CAE1, + 0xD8F3_B49C_ECA4_2A05, + 0xBD56_BE3F_5138_2F73, + 0x45FA_ED58_43B0_BB28, + 0x1C81_3D5C_11BF_1F83, + 0x8AF0_E4B6_D75F_A169, + 0x33EE_18A4_87AD_9999, + 0x3C26_E8EA_B1C9_4410, + 0xB510_102B_C0A8_22F9, + 0x141E_EF31_0CE6_123B, + 0xFC65_B900_59DD_B154, + 0xE015_8640_C5E0_E607, + 0x884E_0798_26C3_A3CF, + 0x930D_0D95_23C5_35FD, + 0x3563_8D75_4E9A_2B00, + 0x4085_FCCF_4046_9DD5, + 0xC4B1_7AD2_8BE2_3A4C, + 0xCAB2_F0FC_6A3E_6A2E, + 0x2860_971A_6B94_3FCD, + 0x3DDE_6EE2_12E3_0446, + 0x6222_F32A_E017_65AE, + 0x5D55_0BB5_4783_08FE, + 0xA9EF_A98D_A0ED_A22A, + 0xC351_A716_86C4_0DA7, + 0x1105_586D_9C86_7C84, + 0xDCFF_EE85_FDA2_2853, + 0xCCFB_D026_2C5E_EF76, + 0xBAF2_94CB_8990_D201, + 0xE694_64F5_2AFA_D975, + 0x94B0_13AF_DF13_3E14, + 0x06A7_D1A3_2823_C958, + 0x6F95_FE51_30F6_1119, + 0xD92A_B34E_462C_06C0, + 0xED7B_DE33_887C_71D2, + 0x7974_6D6E_6518_393E, + 0x5BA4_1938_5D71_3329, + 0x7C1B_A6B9_48A9_7564, + 0x3198_7C19_7BFD_AC67, + 0xDE6C_23C4_4B05_3D02, + 0x581C_49FE_D002_D64D, + 0xDD47_4D63_3826_1571, + 0xAA45_46C3_E473_D062, + 0x928F_CE34_9455_F860, + 0x4816_1BBA_CAAB_94D9, + 0x6391_2430_770E_6F68, + 0x6EC8_A5E6_02C6_641C, + 0x8728_2515_337D_DD2B, + 0x2CDA_6B42_034B_701B, + 0xB03D_37C1_81CB_096D, + 0xE108_4382_66C7_1C6F, + 0x2B31_80C7_EB51_B255, + 0xDF92_B82F_96C0_8BBC, + 0x5C68_C8C0_A632_F3BA, + 0x5504_CC86_1C3D_0556, + 0xABBF_A4E5_5FB2_6B8F, + 0x4184_8B0A_B3BA_CEB4, + 0xB334_A273_AA44_5D32, + 0xBCA6_96F0_A85A_D881, + 0x24F6_EC65_B528_D56C, + 0x0CE1_512E_90F4_524A, + 0x4E9D_D79D_5506_D35A, + 0x2589_05FA_C6CE_9779, + 0x2019_295B_3E10_9B33, + 0xF8A9_478B_73A0_54CC, + 0x2924_F2F9_3441_7EB0, + 0x3993_357D_536D_1BC4, + 0x38A8_1AC2_1DB6_FF8B, + 0x47C4_FBF1_7D60_16BF, + 0x1E0F_AADD_7667_E3F5, + 0x7ABC_FF62_938B_EB96, + 0xA78D_AD94_8FC1_79C9, + 0x8F1F_98B7_2911_E50D, + 0x61E4_8EAE_2712_1A91, + 0x4D62_F7AD_3185_9808, + 0xECEB_A345_EF5C_EAEB, + 0xF5CE_B25E_BC96_84CE, + 0xF633_E20C_B7F7_6221, + 0xA32C_DF06_AB82_93E4, + 0x985A_202C_A5EE_2CA4, + 0xCF0B_8447_CC8A_8FB1, + 0x9F76_5244_9798_59A3, + 0xA8D5_16B1_A124_0017, + 0x0BD7_BA3E_BB5D_C726, + 0xE54B_CA55_B86A_DB39, + 0x1D7A_3AFD_6C47_8063, + 0x519E_C608_E766_9EDD, + 0x0E57_15A2_D149_AA23, + 0x177D_4571_848F_F194, + 0xEEB5_5F32_4101_4C22, + 0x0F5E_5CA1_3A6E_2EC2, + 0x8029_927B_75F5_C361, + 0xAD13_9FAB_C3D6_E436, + 0x0D5D_F1A9_4CCF_402F, + 0x3E8B_D948_BEA5_DFC8, + 0xA5A0_D357_BD3F_F77E, + 0xA2D1_2E25_1F74_F645, + 0x66FD_9E52_5E81_A082, + 0x2E0C_90CE_7F68_7A49, + 0xC2E8_BCBE_BA97_3BC5, + 0x0000_01BC_E509_745F, + 0x4237_77BB_E6DA_B3D6, + 0xD166_1C7E_AEF0_6EB5, + 0xA178_1F35_4DAA_CFD8, + 0x2D11_284A_2B16_AFFC, + 0xF1FC_4F67_FA89_1D1F, + 0x73EC_C25D_CB92_0ADA, + 0xAE61_0C22_C2A1_2651, + 0x96E0_A810_D356_B78A, + 0x5A9A_381F_2FE7_870F, + 0xD5AD_62ED_E94E_5530, + 0xD225_E5E8_368D_1427, + 0x6597_7B70_C7AF_4631, + 0x99F8_89B2_DE39_D74F, + 0x233F_30BF_54E1_D143, + 0x9A96_75D3_D9A6_3C97, + 0x5470_554F_F334_F9A8, + 0x166A_CB74_4A4F_5688, + 0x70C7_4CAA_B2E4_AEAD, + 0xF0D0_9164_6F29_4D12, + 0x57B8_2A89_6840_31D1, + 0xEFD9_5A5A_61BE_0B6B, + 0x2FBD_12E9_69F2_F29A, + 0x9BD3_7013_FEFF_9FE8, + 0x3F9B_0404_D608_5A06, + 0x4940_C1F3_166C_FE15, + 0x0954_2C4D_CDF3_DEFB, + 0xB4C5_2183_85CD_5CE3, + 0xC935_B7DC_4462_A641, + 0x3417_F8A6_8ED3_B63F, + 0xB809_5929_5B21_5B40, + 0xF99C_DAEF_3B8C_8572, + 0x018C_0614_F8FC_B95D, + 0x1B14_ACCD_1A3A_CDF3, + 0x84D4_71F2_00BB_732D, + 0xC1A3_110E_95E8_DA16, + 0x430A_7220_BF1A_82B8, + 0xB77E_090D_39DF_210E, + 0x5EF4_BD9F_3CD0_5E9D, + 0x9D4F_F6DA_7E57_A444, + 0xDA1D_60E1_83D4_A5F8, + 0xB287_C384_1799_8E47, + 0xFE3E_DC12_1BB3_1886, + 0xC7FE_3CCC_980C_CBEF, + 0xE46F_B590_189B_FD03, + 0x3732_FD46_9A4C_57DC, + 0x7EF7_00A0_7CF1_AD65, + 0x59C6_4468_A31D_8859, + 0x762F_B0B4_D45B_61F6, + 0x155B_AED0_9904_7718, + 0x6875_5E4C_3D50_BAA6, + 0xE921_4E7F_22D8_B4DF, + 0x2ADD_BF53_2EAC_95F4, + 0x32AE_3909_B4BD_0109, + 0x834D_F537_B08E_3450, + 0xFA20_9DA8_4220_728D, + 0x9E69_1D9B_9EFE_23F7, + 0x0446_D288_C4AE_8D7F, + 0x7B4C_C524_E169_785B, + 0x21D8_7F01_35CA_1385, + 0xCEBB_400F_137B_8AA5, + 0x272E_2B66_5807_96BE, + 0x3612_2641_25C2_B0DE, + 0x0577_02BD_AD1E_FBB2, + 0xD4BA_BB8E_ACF8_4BE9, + 0x9158_3139_641B_C67B, + 0x8BDC_2DE0_8036_E024, + 0x603C_8156_F49F_68ED, + 0xF7D2_36F7_DBEF_5111, + 0x9727_C459_8AD2_1E80, + 0xA08A_0896_670A_5FD7, + 0xCB4A_8F43_09EB_A9CB, + 0x81AF_564B_0F70_36A1, + 0xC0B9_9AA7_7819_9ABD, + 0x959F_1EC8_3FC8_E952, + 0x8C50_5077_794A_81B9, + 0x3ACA_AF8F_0563_38F0, + 0x07B4_3F50_627A_6778, + 0x4A44_AB49_F5EC_CC77, + 0x3BC3_D6E4_B679_EE98, + 0x9CC0_D4D1_CF14_108C, + 0x4406_C00B_206B_C8A0, + 0x82A1_8854_C8D7_2D89, + 0x67E3_66B3_5C3C_432C, + 0xB923_DD61_102B_37F2, + 0x56AB_2779_D884_271D, + 0xBE83_E1B0_FF15_25AF, + 0xFB7C_65D4_217E_49A9, + 0x6BDB_E0E7_6D48_E7D4, + 0x08DF_8287_45D9_179E, + 0x22EA_6A9A_DD53_BD34, + 0xE36E_141C_5622_200A, + 0x7F80_5D1B_8CB7_50EE, + 0xAFE5_C7A5_9F58_E837, + 0xE27F_996A_4FB1_C23C, + 0xD386_7DFB_0775_F0D0, + 0xD0E6_73DE_6E88_891A, + 0x123A_EB9E_AFB8_6C25, + 0x30F1_D5D5_C145_B895, + 0xBB43_4A2D_EE72_69E7, + 0x78CB_67EC_F931_FA38, + 0xF33B_0372_323B_BF9C, + 0x52D6_6336_FB27_9C74, + 0x505F_33AC_0AFB_4EAA, + 0xE8A5_CD99_A2CC_E187, + 0x5349_7480_1E2D_30BB, + 0x8D2D_5711_D587_6D90, + 0x1F1A_4128_91BC_038E, + 0xD6E2_E71D_82E5_6648, + 0x7403_6C3A_4977_32B7, + 0x89B6_7ED9_6361_F5AB, + 0xFFED_95D8_F1EA_02A2, + 0xE72B_3BD6_1464_D43D, + 0xA630_0F17_0BDC_4820, + 0xEBC1_8760_ED78_A77A, +]; + +pub(crate) static T2: [u64; 256] = [ + 0xE6A6_BE5A_05A1_2138, + 0xB5A1_22A5_B4F8_7C98, + 0x563C_6089_140B_6990, + 0x4C46_CB2E_391F_5DD5, + 0xD932_ADDB_C9B7_9434, + 0x08EA_70E4_2015_AFF5, + 0xD765_A667_3E47_8CF1, + 0xC4FB_757E_AB27_8D99, + 0xDF11_C686_2D6E_0692, + 0xDDEB_84F1_0D7F_3B16, + 0x6F2E_F604_A665_EA04, + 0x4A8E_0F0F_F0E0_DFB3, + 0xA5ED_EEF8_3DBC_BA51, + 0xFC4F_0A2A_0EA4_371E, + 0xE83E_1DA8_5CB3_8429, + 0xDC8F_F882_BA1B_1CE2, + 0xCD45_505E_8353_E80D, + 0x18D1_9A00_D4DB_0717, + 0x34A0_CFED_A5F3_8101, + 0x0BE7_7E51_8887_CAF2, + 0x1E34_1438_B3C4_5136, + 0xE057_97F4_9089_CCF9, + 0xFFD2_3F9D_F259_1D14, + 0x543D_DA22_8595_C5CD, + 0x661F_81FD_9905_2A33, + 0x8736_E641_DB0F_7B76, + 0x1522_7725_418E_5307, + 0xE25F_7F46_162E_B2FA, + 0x48A8_B212_6C13_D9FE, + 0xAFDC_5417_92E7_6EEA, + 0x03D9_12BF_C6D1_898F, + 0x31B1_AAFA_1B83_F51B, + 0xF1AC_2796_E42A_B7D9, + 0x40A3_A7D7_FCD2_EBAC, + 0x1056_136D_0AFB_BCC5, + 0x7889_E1DD_9A6D_0C85, + 0xD335_2578_2A79_74AA, + 0xA7E2_5D09_078A_C09B, + 0xBD41_38B3_EAC6_EDD0, + 0x920A_BFBE_71EB_9E70, + 0xA2A5_D0F5_4FC2_625C, + 0xC054_E36B_0B12_90A3, + 0xF6DD_59FF_62FE_932B, + 0x3537_3545_11A8_AC7D, + 0xCA84_5E91_72FA_DCD4, + 0x84F8_2B60_329D_20DC, + 0x79C6_2CE1_CD67_2F18, + 0x8B09_A2AD_D124_642C, + 0xD0C1_E96A_19D9_E726, + 0x5A78_6A9B_4BA9_500C, + 0x0E02_0336_634C_43F3, + 0xC17B_474A_EB66_D822, + 0x6A73_1AE3_EC9B_AAC2, + 0x8226_667A_E084_0258, + 0x67D4_5676_91CA_ECA5, + 0x1D94_155C_4875_ADB5, + 0x6D00_FD98_5B81_3FDF, + 0x5128_6EFC_B774_CD06, + 0x5E88_3447_1FA7_44AF, + 0xF72C_A0AE_E761_AE2E, + 0xBE40_E4CD_AEE8_E09A, + 0xE997_0BBB_5118_F665, + 0x726E_4BEB_33DF_1964, + 0x703B_0007_2919_9762, + 0x4631_D816_F5EF_30A7, + 0xB880_B5B5_1504_A6BE, + 0x6417_93C3_7ED8_4B6C, + 0x7B21_ED77_F6E9_7D96, + 0x7763_0631_2EF9_6B73, + 0xAE52_8948_E86F_F3F4, + 0x53DB_D7F2_86A3_F8F8, + 0x16CA_DCE7_4CFC_1063, + 0x005C_19BD_FA52_C6DD, + 0x6886_8F5D_64D4_6AD3, + 0x3A9D_512C_CF1E_186A, + 0x367E_62C2_3856_60AE, + 0xE359_E7EA_77DC_B1D7, + 0x526C_0773_749A_BE6E, + 0x735A_E5F9_D09F_734B, + 0x493F_C7CC_8A55_8BA8, + 0xB0B9_C153_3041_AB45, + 0x3219_58BA_470A_59BD, + 0x852D_B00B_5F46_C393, + 0x9120_9B2B_D336_B0E5, + 0x6E60_4F7D_659E_F19F, + 0xB99A_8AE2_782C_CB24, + 0xCCF5_2AB6_C814_C4C7, + 0x4727_D9AF_BE11_727B, + 0x7E95_0D0C_0121_B34D, + 0x756F_4356_70AD_471F, + 0xF5AD_D442_615A_6849, + 0x4E87_E099_80B9_957A, + 0x2ACF_A1DF_50AE_E355, + 0xD898_263A_FD2F_D556, + 0xC8F4_924D_D80C_8FD6, + 0xCF99_CA3D_754A_173A, + 0xFE47_7BAC_AF91_BF3C, + 0xED53_71F6_D690_C12D, + 0x831A_5C28_5E68_7094, + 0xC5D3_C90A_3708_A0A4, + 0x0F7F_9037_17D0_6580, + 0x19F9_BB13_B8FD_F27F, + 0xB1BD_6F1B_4D50_2843, + 0x1C76_1BA3_8FFF_4012, + 0x0D15_30C4_E2E2_1F3B, + 0x8943_CE69_A737_2C8A, + 0xE518_4E11_FEB5_CE66, + 0x618B_DB80_BD73_6621, + 0x7D29_BAD6_8B57_4D0B, + 0x81BB_613E_25E6_FE5B, + 0x071C_9C10_BC07_913F, + 0xC7BE_EB79_09AC_2D97, + 0xC3E5_8D35_3BC5_D757, + 0xEB01_7892_F38F_61E8, + 0xD4EF_FB9C_9B1C_C21A, + 0x9972_7D26_F494_F7AB, + 0xA3E0_63A2_956B_3E03, + 0x9D4A_8B9A_4AA0_9C30, + 0x3F6A_B7D5_0009_0FB4, + 0x9CC0_F2A0_5726_8AC0, + 0x3DEE_9D2D_EDBF_42D1, + 0x330F_49C8_7960_A972, + 0xC6B2_7202_8742_1B41, + 0x0AC5_9EC0_7C00_369C, + 0xEF4E_AC49_CB35_3425, + 0xF450_244E_EF01_29D8, + 0x8ACC_46E5_CAF4_DEB6, + 0x2FFE_AB63_9892_63F7, + 0x8F7C_B9FE_5D7A_4578, + 0x5BD8_F764_4E63_4635, + 0x427A_7315_BF2D_C900, + 0x17D0_C4AA_2125_261C, + 0x3992_486C_9351_8E50, + 0xB4CB_FEE0_A2D7_D4C3, + 0x7C75_D620_2C5D_DD8D, + 0xDBC2_95D8_E35B_6C61, + 0x60B3_69D3_0203_2B19, + 0xCE42_685F_DCE4_4132, + 0x06F3_DDB9_DDF6_5610, + 0x8EA4_D21D_B5E1_48F0, + 0x20B0_FCE6_2FCD_496F, + 0x2C1B_9123_58B0_EE31, + 0xB283_17B8_18F5_A308, + 0xA89C_1E18_9CA6_D2CF, + 0x0C6B_1857_6AAA_DBC8, + 0xB65D_EAA9_1299_FAE3, + 0xFB2B_794B_7F10_27E7, + 0x04E4_317F_443B_5BEB, + 0x4B85_2D32_5939_D0A6, + 0xD5AE_6BEE_FB20_7FFC, + 0x3096_82B2_81C7_D374, + 0xBAE3_09A1_94C3_B475, + 0x8CC3_F97B_13B4_9F05, + 0x98A9_422F_F829_3967, + 0x244B_16B0_1076_FF7C, + 0xF8BF_571C_663D_67EE, + 0x1F0D_6758_EEE3_0DA1, + 0xC9B6_11D9_7ADE_B9B7, + 0xB7AF_D588_7B6C_57A2, + 0x6290_AE84_6B98_4FE1, + 0x94DF_4CDE_ACC1_A5FD, + 0x058A_5BD1_C548_3AFF, + 0x6316_6CC1_42BA_3C37, + 0x8DB8_526E_B2F7_6F40, + 0xE108_8003_6F0D_6D4E, + 0x9E05_23C9_971D_311D, + 0x45EC_2824_CC7C_D691, + 0x575B_8359_E623_82C9, + 0xFA9E_400D_C488_9995, + 0xD182_3ECB_4572_1568, + 0xDAFD_983B_8206_082F, + 0xAA7D_2908_2386_A8CB, + 0x269F_CD44_03B8_7588, + 0x1B91_F5F7_28BD_D1E0, + 0xE466_9F39_0402_01F6, + 0x7A1D_7C21_8CF0_4ADE, + 0x6562_3C29_D79C_E5CE, + 0x2368_4490_96C0_0BB1, + 0xAB9B_F187_9DA5_03BA, + 0xBC23_ECB1_A458_058E, + 0x9A58_DF01_BB40_1ECC, + 0xA070_E868_A85F_143D, + 0x4FF1_8830_7DF2_239E, + 0x14D5_65B4_1A64_1183, + 0xEE13_3374_5270_1602, + 0x950E_3DCF_3F28_5E09, + 0x5993_0254_B9C8_0953, + 0x3BF2_9940_8930_DA6D, + 0xA955_943F_5369_1387, + 0xA15E_DECA_A9CB_8784, + 0x2914_2127_352B_E9A0, + 0x76F0_371F_FF4E_7AFB, + 0x0239_F450_274F_2228, + 0xBB07_3AF0_1D5E_868B, + 0xBFC8_0571_C10E_96C1, + 0xD267_0885_6822_2E23, + 0x9671_A3D4_8E80_B5B0, + 0x55B5_D38A_E193_BB81, + 0x693A_E2D0_A18B_04B8, + 0x5C48_B4EC_ADD5_335F, + 0xFD74_3B19_4916_A1CA, + 0x2577_0181_34BE_98C4, + 0xE779_87E8_3C54_A4AD, + 0x28E1_1014_DA33_E1B9, + 0x270C_C59E_226A_A213, + 0x7149_5F75_6D1A_5F60, + 0x9BE8_53FB_60AF_EF77, + 0xADC7_86A7_F744_3DBF, + 0x0904_4561_73B2_9A82, + 0x58BC_7A66_C232_BD5E, + 0xF306_558C_673A_C8B2, + 0x41F6_39C6_B6C9_772A, + 0x216D_EFE9_9FDA_35DA, + 0x1164_0CC7_1C7B_E615, + 0x93C4_3694_565C_5527, + 0xEA03_8E62_4677_7839, + 0xF9AB_F3CE_5A3E_2469, + 0x741E_768D_0FD3_12D2, + 0x0144_B883_CED6_52C6, + 0xC20B_5A5B_A33F_8552, + 0x1AE6_9633_C343_5A9D, + 0x97A2_8CA4_088C_FDEC, + 0x8824_A43C_1E96_F420, + 0x3761_2FA6_6EEE_A746, + 0x6B4C_B165_F9CF_0E5A, + 0x43AA_1C06_A0AB_FB4A, + 0x7F4D_C26F_F162_796B, + 0x6CBA_CC8E_54ED_9B0F, + 0xA6B7_FFEF_D2BB_253E, + 0x2E25_BC95_B0A2_9D4F, + 0x86D6_A58B_DEF1_388C, + 0xDED7_4AC5_76B6_F054, + 0x8030_BDBC_2B45_805D, + 0x3C81_AF70_E94D_9289, + 0x3EFF_6DDA_9E31_00DB, + 0xB38D_C39F_DFCC_8847, + 0x1238_8552_8D17_B87E, + 0xF2DA_0ED2_40B1_B642, + 0x44CE_FADC_D54B_F9A9, + 0x1312_200E_433C_7EE6, + 0x9FFC_C84F_3A78_C748, + 0xF0CD_1F72_2485_76BB, + 0xEC69_7405_3638_CFE4, + 0x2BA7_B67C_0CEC_4E4C, + 0xAC2F_4DF3_E5CE_32ED, + 0xCB33_D143_26EA_4C11, + 0xA4E9_044C_C77E_58BC, + 0x5F51_3293_D934_FCEF, + 0x5DC9_6455_06E5_5444, + 0x50DE_418F_317D_E40A, + 0x388C_B31A_69DD_E259, + 0x2DB4_A834_5582_0A86, + 0x9010_A91E_8471_1AE9, + 0x4DF7_F0B7_B149_8371, + 0xD62A_2EAB_C097_7179, + 0x22FA_C097_AA8D_5C0E, +]; + +pub(crate) static T3: [u64; 256] = [ + 0xF49F_CC2F_F1DA_F39B, + 0x487F_D5C6_6FF2_9281, + 0xE8A3_0667_FCDC_A83F, + 0x2C9B_4BE3_D2FC_CE63, + 0xDA3F_F74B_93FB_BBC2, + 0x2FA1_65D2_FE70_BA66, + 0xA103_E279_970E_93D4, + 0xBECD_EC77_B0E4_5E71, + 0xCFB4_1E72_3985_E497, + 0xB70A_AA02_5EF7_5017, + 0xD423_09F0_3840_B8E0, + 0x8EFC_1AD0_3589_8579, + 0x96C6_920B_E2B2_ABC5, + 0x66AF_4163_375A_9172, + 0x2174_ABDC_CA71_27FB, + 0xB33C_CEA6_4A72_FF41, + 0xF04A_4933_0830_66A5, + 0x8D97_0ACD_D728_9AF5, + 0x8F96_E8E0_31C8_C25E, + 0xF3FE_C022_7687_5D47, + 0xEC7B_F310_0561_90DD, + 0xF5AD_B0AE_BB0F_1491, + 0x9B50_F885_0FD5_8892, + 0x4975_4883_58B7_4DE8, + 0xA335_4FF6_9153_1C61, + 0x0702_BBE4_81D2_C6EE, + 0x89FB_2405_7DED_ED98, + 0xAC30_7513_8596_E902, + 0x1D2D_3580_1727_72ED, + 0xEB73_8FC2_8E6B_C30D, + 0x5854_EF8F_6304_4326, + 0x9E5C_5232_5ADD_3BBE, + 0x90AA_53CF_325C_4623, + 0xC1D2_4D51_349D_D067, + 0x2051_CFEE_A69E_A624, + 0x1322_0F0A_862E_7E4F, + 0xCE39_3994_04E0_4864, + 0xD9C4_2CA4_7086_FCB7, + 0x685A_D223_8A03_E7CC, + 0x0664_84B2_AB2F_F1DB, + 0xFE9D_5D70_EFBF_79EC, + 0x5B13_B9DD_9C48_1854, + 0x15F0_D475_ED15_09AD, + 0x0BEB_CD06_0EC7_9851, + 0xD58C_6791_183A_B7F8, + 0xD118_7C50_52F3_EEE4, + 0xC95D_1192_E54E_82FF, + 0x86EE_A14C_B9AC_6CA2, + 0x3485_BEB1_5367_7D5D, + 0xDD19_1D78_1F8C_492A, + 0xF608_66BA_A784_EBF9, + 0x518F_643B_A2D0_8C74, + 0x8852_E956_E108_7C22, + 0xA768_CB8D_C410_AE8D, + 0x3804_7726_BFEC_8E1A, + 0xA677_38B4_CD3B_45AA, + 0xAD16_691C_EC0D_DE19, + 0xC6D4_3193_8046_2E07, + 0xC5A5_876D_0BA6_1938, + 0x16B9_FA1F_A58F_D840, + 0x188A_B117_3CA7_4F18, + 0xABDA_2F98_C99C_021F, + 0x3E05_80AB_134A_E816, + 0x5F3B_05B7_7364_5ABB, + 0x2501_A2BE_5575_F2F6, + 0x1B2F_7400_4E7E_8BA9, + 0x1CD7_5803_71E8_D953, + 0x7F6E_D895_6276_4E30, + 0xB159_26FF_596F_003D, + 0x9F65_293D_A8C5_D6B9, + 0x6ECE_F04D_D690_F84C, + 0x4782_275F_FF33_AF88, + 0xE414_3308_3F82_0801, + 0xFD0D_FE40_9A1A_F9B5, + 0x4325_A334_2CDB_396B, + 0x8AE7_7E62_B301_B252, + 0xC36F_9E9F_6655_615A, + 0x8545_5A2D_92D3_2C09, + 0xF2C7_DEA9_4947_7485, + 0x63CF_B4C1_33A3_9EBA, + 0x83B0_40CC_6EBC_5462, + 0x3B94_54C8_FDB3_26B0, + 0x56F5_6A9E_87FF_D78C, + 0x2DC2_940D_99F4_2BC6, + 0x98F7_DF09_6B09_6E2D, + 0x19A6_E01E_3AD8_52BF, + 0x42A9_9CCB_DBD4_B40B, + 0xA599_98AF_45E9_C559, + 0x3662_95E8_07D9_3186, + 0x6B48_181B_FAA1_F773, + 0x1FEC_57E2_157A_0A1D, + 0x4667_446A_F620_1AD5, + 0xE615_EBCA_CFB0_F075, + 0xB8F3_1F4F_6829_0778, + 0x2271_3ED6_CE22_D11E, + 0x3057_C1A7_2EC3_C93B, + 0xCB46_ACC3_7C3F_1F2F, + 0xDBB8_93FD_02AA_F50E, + 0x331F_D92E_600B_9FCF, + 0xA498_F961_48EA_3AD6, + 0xA8D8_426E_8B6A_83EA, + 0xA089_B274_B773_5CDC, + 0x87F6_B373_1E52_4A11, + 0x1188_08E5_CBC9_6749, + 0x9906_E4C7_B19B_D394, + 0xAFED_7F7E_9B24_A20C, + 0x6509_EADE_EB36_44A7, + 0x6C1E_F1D3_E8EF_0EDE, + 0xB9C9_7D43_E979_8FB4, + 0xA2F2_D784_740C_28A3, + 0x7B84_9647_6197_566F, + 0x7A5B_E3E6_B65F_069D, + 0xF963_30ED_78BE_6F10, + 0xEEE6_0DE7_7A07_6A15, + 0x2B4B_EE4A_A08B_9BD0, + 0x6A56_A63E_C7B8_894E, + 0x0212_1359_BA34_FEF4, + 0x4CBF_99F8_2837_03FC, + 0x3980_7135_0CAF_30C8, + 0xD0A7_7A89_F017_687A, + 0xF1C1_A9EB_9E42_3569, + 0x8C79_7628_2DEE_8199, + 0x5D17_37A5_DD1F_7ABD, + 0x4F53_433C_09A9_FA80, + 0xFA8B_0C53_DF7C_A1D9, + 0x3FD9_DCBC_886C_CB77, + 0xC040_917C_A91B_4720, + 0x7DD0_0142_F9D1_DCDF, + 0x8476_FC1D_4F38_7B58, + 0x23F8_E7C5_F331_6503, + 0x032A_2244_E7E3_7339, + 0x5C87_A5D7_50F5_A74B, + 0x082B_4CC4_3698_992E, + 0xDF91_7BEC_B858_F63C, + 0x3270_B8FC_5BF8_6DDA, + 0x10AE_72BB_29B5_DD76, + 0x576A_C94E_7700_362B, + 0x1AD1_12DA_C61E_FB8F, + 0x691B_C30E_C5FA_A427, + 0xFF24_6311_CC32_7143, + 0x3142_368E_30E5_3206, + 0x7138_0E31_E02C_A396, + 0x958D_5C96_0AAD_76F1, + 0xF8D6_F430_C16D_A536, + 0xC8FF_D13F_1BE7_E1D2, + 0x7578_AE66_004D_DBE1, + 0x0583_3F01_067B_E646, + 0xBB34_B5AD_3BFE_586D, + 0x095F_34C9_A12B_97F0, + 0x247A_B645_25D6_0CA8, + 0xDCDB_C6F3_0174_77D1, + 0x4A2E_14D4_DECA_D24D, + 0xBDB5_E6D9_BE0A_1EEB, + 0x2A7E_70F7_7943_01AB, + 0xDEF4_2D8A_2705_40FD, + 0x0107_8EC0_A34C_22C1, + 0xE5DE_511A_F4C1_6387, + 0x7EBB_3A52_BD9A_330A, + 0x7769_7857_AA7D_6435, + 0x004E_8316_03AE_4C32, + 0xE7A2_1020_AD78_E312, + 0x9D41_A70C_6AB4_20F2, + 0x28E0_6C18_EA11_41E6, + 0xD2B2_8CBD_984F_6B28, + 0x26B7_5F6C_446E_9D83, + 0xBA47_568C_4D41_8D7F, + 0xD80B_ADBF_E618_3D8E, + 0x0E20_6D7F_5F16_6044, + 0xE258_A439_11CB_CA3E, + 0x723A_1746_B21D_C0BC, + 0xC7CA_A854_F5D7_CDD3, + 0x7CAC_3288_3D26_1D9C, + 0x7690_C264_23BA_942C, + 0x17E5_5524_4780_42B8, + 0xE0BE_4776_56A2_389F, + 0x4D28_9B5E_67AB_2DA0, + 0x4486_2B9C_8FBB_FD31, + 0xB47C_C804_9D14_1365, + 0x822C_1B36_2B91_C793, + 0x4EB1_4655_FB13_DFD8, + 0x1ECB_BA07_14E2_A97B, + 0x6143_459D_5CDE_5F14, + 0x53A8_FBF1_D5F0_AC89, + 0x97EA_04D8_1C5E_5B00, + 0x6221_81A8_D4FD_B3F3, + 0xE9BC_D341_572A_1208, + 0x1411_2586_43CC_E58A, + 0x9144_C5FE_A4C6_E0A4, + 0x0D33_D065_65CF_620F, + 0x54A4_8D48_9F21_9CA1, + 0xC43E_5EAC_6D63_C821, + 0xA972_8B3A_7277_0DAF, + 0xD793_4E7B_20DF_87EF, + 0xE355_03B6_1A3E_86E5, + 0xCAE3_21FB_C819_D504, + 0x129A_50B3_AC60_BFA6, + 0xCD5E_68EA_7E9F_B6C3, + 0xB01C_9019_9483_B1C7, + 0x3DE9_3CD5_C295_376C, + 0xAED5_2EDF_2AB9_AD13, + 0x2E60_F512_C0A0_7884, + 0xBC3D_86A3_E362_10C9, + 0x3526_9D9B_1639_51CE, + 0x0C7D_6E2A_D0CD_B5FA, + 0x59E8_6297_D87F_5733, + 0x298E_F221_898D_B0E7, + 0x5500_0029_D1A5_AA7E, + 0x8BC0_8AE1_B506_1B45, + 0xC2C3_1C2B_6C92_703A, + 0x94CC_596B_AF25_EF42, + 0x0A1D_73DB_2254_0456, + 0x04B6_A0F9_D9C4_179A, + 0xEFFD_AFA2_AE3D_3C60, + 0xF7C8_075B_B494_96C4, + 0x9CC5_C714_1D1C_D4E3, + 0x78BD_1638_218E_5534, + 0xB2F1_1568_F850_246A, + 0xEDFA_BCFA_9502_BC29, + 0x796C_E5F2_DA23_051B, + 0xAAE1_28B0_DC93_537C, + 0x3A49_3DA0_EE4B_29AE, + 0xB5DF_6B2C_4168_95D7, + 0xFCAB_BD25_122D_7F37, + 0x7081_0B58_105D_C4B1, + 0xE10F_DD37_F788_2A90, + 0x524D_CAB5_518A_3F5C, + 0x3C9E_8587_8451_255B, + 0x4029_8281_19BD_34E2, + 0x74A0_5B6F_5D3C_ECCB, + 0xB610_0215_42E1_3ECA, + 0x0FF9_79D1_2F59_E2AC, + 0x6037_DA27_E4F9_CC50, + 0x5E92_975A_0DF1_847D, + 0xD66D_E190_D3E6_23FE, + 0x5032_D6B8_7B56_8048, + 0x9A36_B7CE_8235_216E, + 0x8027_2A7A_24F6_4B4A, + 0x93EF_ED8B_8C69_16F7, + 0x37DD_BFF4_4CCE_1555, + 0x4B95_DB5D_4B99_BD25, + 0x92D3_FDA1_6981_2FC0, + 0xFB1A_4A9A_9066_0BB6, + 0x730C_1969_46A4_B9B2, + 0x81E2_89AA_7F49_DA68, + 0x6466_9A0F_83B1_A05F, + 0x27B3_FF7D_9644_F48B, + 0xCC6B_615C_8DB6_75B3, + 0x674F_20B9_BCEB_BE95, + 0x6F31_2382_7565_5982, + 0x5AE4_8871_3E45_CF05, + 0xBF61_9F99_54C2_1157, + 0xEABA_C460_40A8_EAE9, + 0x454C_6FE9_F2C0_C1CD, + 0x419C_F649_6412_691C, + 0xD3DC_3BEF_265B_0F70, + 0x6D0E_60F5_C357_8A9E, +]; + +pub(crate) static T4: [u64; 256] = [ + 0x5B0E_6085_2632_3C55, + 0x1A46_C1A9_FA1B_59F5, + 0xA9E2_45A1_7C4C_8FFA, + 0x65CA_5159_DB29_55D7, + 0x05DB_0A76_CE35_AFC2, + 0x81EA_C77E_A911_3D45, + 0x528E_F88A_B6AC_0A0D, + 0xA09E_A253_597B_E3FF, + 0x430D_DFB3_AC48_CD56, + 0xC4B3_A67A_F45C_E46F, + 0x4ECE_CFD8_FBE2_D05E, + 0x3EF5_6F10_B399_35F0, + 0x0B22_D682_9CD6_19C6, + 0x17FD_460A_74DF_2069, + 0x6CF8_CC8E_8510_ED40, + 0xD6C8_24BF_3A6E_CAA7, + 0x6124_3D58_1A81_7049, + 0x048B_ACB6_BBC1_63A2, + 0xD9A3_8AC2_7D44_CC32, + 0x7FDD_FF5B_AAF4_10AB, + 0xAD6D_495A_A804_824B, + 0xE1A6_A74F_2D8C_9F94, + 0xD4F7_8512_35DE_E8E3, + 0xFD4B_7F88_6540_D893, + 0x247C_2004_2AA4_BFDA, + 0x096E_A1C5_17D1_327C, + 0xD569_66B4_361A_6685, + 0x277D_A5C3_1221_057D, + 0x94D5_9893_A43A_CFF7, + 0x64F0_C51C_CDC0_2281, + 0x3D33_BCC4_FF61_89DB, + 0xE005_CB18_4CE6_6AF1, + 0xFF5C_CD1D_1DB9_9BEA, + 0xB0B8_54A7_FE42_980F, + 0x7BD4_6A6A_718D_4B9F, + 0xD10F_A8CC_22A5_FD8C, + 0xD314_8495_2BE4_BD31, + 0xC7FA_975F_CB24_3847, + 0x4886_ED1E_5846_C407, + 0x28CD_DB79_1EB7_0B04, + 0xC2B0_0BE2_F573_417F, + 0x5C95_9045_2180_F877, + 0x7A6B_DDFF_F370_EB00, + 0xCE50_9E38_D6D9_D6A4, + 0xEBEB_0F00_647F_A702, + 0x1DCC_06CF_7660_6F06, + 0xE4D9_F28B_A286_FF0A, + 0xD85A_305D_C918_C262, + 0x475B_1D87_3222_5F54, + 0x2D4F_B516_68CC_B5FE, + 0xA679_B9D9_D72B_BA20, + 0x5384_1C0D_912D_43A5, + 0x3B7E_AA48_BF12_A4E8, + 0x781E_0E47_F22F_1DDF, + 0xEFF2_0CE6_0AB5_0973, + 0x20D2_61D1_9DFF_B742, + 0x16A1_2B03_062A_2E39, + 0x1960_EB22_3965_0495, + 0x251C_16FE_D50E_B8B8, + 0x9AC0_C330_F826_016E, + 0xED15_2665_953E_7671, + 0x02D6_3194_A636_9570, + 0x5074_F083_94B1_C987, + 0x70BA_598C_90B2_5CE1, + 0x794A_1581_0B97_42F6, + 0x0D59_25E9_FCAF_8C6C, + 0x3067_716C_D868_744E, + 0x910A_B077_E8D7_731B, + 0x6A61_BBDB_5AC4_2F61, + 0x9351_3EFB_F085_1567, + 0xF494_724B_9E83_E9D5, + 0xE887_E198_5C09_648D, + 0x34B1_D3C6_7537_0CFD, + 0xDC35_E433_BC0D_255D, + 0xD0AA_B842_3413_1BE0, + 0x0804_2A50_B48B_7EAF, + 0x9997_C4EE_44A3_AB35, + 0x829A_7B49_2017_99D0, + 0x263B_8307_B7C5_4441, + 0x752F_95F4_FD6A_6CA6, + 0x9272_1740_2C08_C6E5, + 0x2A8A_B754_A795_D9EE, + 0xA442_F755_2F72_943D, + 0x2C31_334E_1978_1208, + 0x4FA9_8D7C_EAEE_6291, + 0x55C3_862F_665D_B309, + 0xBD06_1017_5D53_B1F3, + 0x46FE_6CB8_4041_3F27, + 0x3FE0_3792_DF0C_FA59, + 0xCFE7_0037_2EB8_5E8F, + 0xA7BE_29E7_ADBC_E118, + 0xE544_EE5C_DE84_31DD, + 0x8A78_1B1B_41F1_873E, + 0xA5C9_4C78_A0D2_F0E7, + 0x3941_2E28_77B6_0728, + 0xA126_5EF3_AFC9_A62C, + 0xBCC2_770C_6A25_06C5, + 0x3AB6_6DD5_DCE1_CE12, + 0xE654_99D0_4A67_5B37, + 0x7D8F_5234_81BF_D216, + 0x0F6F_64FC_EC15_F389, + 0x74EF_BE61_8B5B_13C8, + 0xACDC_82B7_1427_3E1D, + 0xDD40_BFE0_0319_9D17, + 0x37E9_9257_E7E0_61F8, + 0xFA52_6269_0477_5AAA, + 0x8BBB_F63A_463D_56F9, + 0xF001_3F15_43A2_6E64, + 0xA830_7E9F_879E_C898, + 0xCC4C_27A4_1501_77CC, + 0x1B43_2F2C_CA1D_3348, + 0xDE1D_1F8F_9F6F_A013, + 0x6066_02A0_47A7_DDD6, + 0xD237_AB64_CC1C_B2C7, + 0x9B93_8E72_25FC_D1D3, + 0xEC4E_0370_8E0F_F476, + 0xFEB2_FBDA_3D03_C12D, + 0xAE0B_CED2_EE43_889A, + 0x22CB_8923_EBFB_4F43, + 0x6936_0D01_3CF7_396D, + 0x855E_3602_D2D4_E022, + 0x0738_05BA_D01F_784C, + 0x33E1_7A13_3852_F546, + 0xDF48_7405_8AC7_B638, + 0xBA92_B29C_678A_A14A, + 0x0CE8_9FC7_6CFA_ADCD, + 0x5F9D_4E09_0833_9E34, + 0xF1AF_E929_1F59_23B9, + 0x6E34_80F6_0F4A_265F, + 0xEEBF_3A2A_B29B_841C, + 0xE219_38A8_8F91_B4AD, + 0x57DF_EFF8_45C6_D3C3, + 0x2F00_6B0B_F62C_AAF2, + 0x62F4_79EF_6F75_EE78, + 0x11A5_5AD4_1C89_16A9, + 0xF229_D290_84FE_D453, + 0x42F1_C27B_16B0_00E6, + 0x2B1F_7674_9823_C074, + 0x4B76_ECA3_C274_5360, + 0x8C98_F463_B916_91BD, + 0x14BC_C93C_F1AD_E66A, + 0x8885_213E_6D45_8397, + 0x8E17_7DF0_274D_4711, + 0xB49B_73B5_503F_2951, + 0x1016_8168_C3F9_6B6B, + 0x0E3D_963B_63CA_B0AE, + 0x8DFC_4B56_55A1_DB14, + 0xF789_F135_6E14_DE5C, + 0x683E_68AF_4E51_DAC1, + 0xC9A8_4F9D_8D4B_0FD9, + 0x3691_E03F_52A0_F9D1, + 0x5ED8_6E46_E187_8E80, + 0x3C71_1A0E_99D0_7150, + 0x5A08_65B2_0C4E_9310, + 0x56FB_FC1F_E4F0_682E, + 0xEA8D_5DE3_105E_DF9B, + 0x71AB_FDB1_2379_187A, + 0x2EB9_9DE1_BEE7_7B9C, + 0x21EC_C0EA_33CF_4523, + 0x59A4_D752_1805_C7A1, + 0x3896_F5EB_56AE_7C72, + 0xAA63_8F3D_B18F_75DC, + 0x9F39_358D_ABE9_808E, + 0xB7DE_FA91_C00B_72AC, + 0x6B55_41FD_6249_2D92, + 0x6DC6_DEE8_F92E_4D5B, + 0x353F_57AB_C4BE_EA7E, + 0x7357_69D6_DA56_90CE, + 0x0A23_4AA6_4239_1484, + 0xF6F9_5080_28F8_0D9D, + 0xB8E3_19A2_7AB3_F215, + 0x31AD_9C11_5134_1A4D, + 0x773C_22A5_7BEF_5805, + 0x45C7_561A_0796_8633, + 0xF913_DA9E_249D_BE36, + 0xDA65_2D9B_78A6_4C68, + 0x4C27_A97F_3BC3_34EF, + 0x7662_1220_E66B_17F4, + 0x9677_4389_9ACD_7D0B, + 0xF3EE_5BCA_E0ED_6782, + 0x409F_7536_00C8_79FC, + 0x06D0_9A39_B592_6DB6, + 0x6F83_AEB0_317A_C588, + 0x01E6_CA4A_8638_1F21, + 0x66FF_3462_D19F_3025, + 0x7220_7C24_DDFD_3BFB, + 0x4AF6_B6D3_E2EC_E2EB, + 0x9C99_4DBE_C7EA_08DE, + 0x49AC_E597_B09A_8BC4, + 0xB38C_4766_CF07_97BA, + 0x131B_9373_C57C_2A75, + 0xB182_2CCE_6193_1E58, + 0x9D75_55B9_09BA_1C0C, + 0x127F_AFDD_937D_11D2, + 0x29DA_3BAD_C66D_92E4, + 0xA2C1_D571_54C2_ECBC, + 0x58C5_134D_82F6_FE24, + 0x1C3A_E351_5B62_274F, + 0xE907_C82E_01CB_8126, + 0xF8ED_0919_13E3_7FCB, + 0x3249_D8F9_C800_46C9, + 0x80CF_9BED_E388_FB63, + 0x1881_539A_116C_F19E, + 0x5103_F3F7_6BD5_2457, + 0x15B7_E6F5_AE47_F7A8, + 0xDBD7_C6DE_D47E_9CCF, + 0x44E5_5C41_0228_BB1A, + 0xB647_D425_5EDB_4E99, + 0x5D11_882B_B8AA_FC30, + 0xF509_8BBB_29D3_212A, + 0x8FB5_EA14_E902_96B3, + 0x677B_9421_57DD_025A, + 0xFB58_E7C0_A390_ACB5, + 0x89D3_674C_83BD_4A01, + 0x9E2D_A4DF_4BF3_B93B, + 0xFCC4_1E32_8CAB_4829, + 0x03F3_8C96_BA58_2C52, + 0xCAD1_BDBD_7FD8_5DB2, + 0xBBB4_42C1_6082_AE83, + 0xB95F_E86B_A5DA_9AB0, + 0xB22E_0467_3771_A93F, + 0x8453_58C9_4931_52D8, + 0xBE2A_4886_97B4_541E, + 0x95A2_DC2D_D38E_6966, + 0xC02C_11AC_923C_852B, + 0x2388_B199_0DF2_A87B, + 0x7C80_08FA_1B4F_37BE, + 0x1F70_D0C8_4D54_E503, + 0x5490_ADEC_7ECE_57D4, + 0x002B_3C27_D906_3A3A, + 0x7EAE_A384_8030_A2BF, + 0xC602_326D_ED20_03C0, + 0x83A7_287D_69A9_4086, + 0xC57A_5FCB_30F5_7A8A, + 0xB568_44E4_79EB_E779, + 0xA373_B40F_05DC_BCE9, + 0xD71A_786E_8857_0EE2, + 0x879C_BACD_BDE8_F6A0, + 0x976A_D1BC_C164_A32F, + 0xAB21_E25E_9666_D78B, + 0x9010_63AA_E5E5_C33C, + 0x9818_B344_4869_8D90, + 0xE364_87AE_3E1E_8ABB, + 0xAFBD_F931_893B_DCB4, + 0x6345_A0DC_5FBB_D519, + 0x8628_FE26_9B94_65CA, + 0x1E5D_0160_3F9C_51EC, + 0x4DE4_4006_A150_49B7, + 0xBF6C_70E5_F776_CBB1, + 0x4112_18F2_EF55_2BED, + 0xCB0C_0708_705A_36A3, + 0xE74D_1475_4F98_6044, + 0xCD56_D943_0EA8_280E, + 0xC125_91D7_535F_5065, + 0xC832_23F1_720A_EF96, + 0xC3A0_396F_7363_A51F, +]; diff --git a/tiger/tests/data/tiger.blb b/tiger/tests/data/tiger.blb new file mode 100644 index 000000000..c936452a2 Binary files /dev/null and b/tiger/tests/data/tiger.blb differ diff --git a/tiger/tests/data/tiger2.blb b/tiger/tests/data/tiger2.blb new file mode 100644 index 000000000..cbfb6c4a2 Binary files /dev/null and b/tiger/tests/data/tiger2.blb differ diff --git a/tiger/tests/mod.rs b/tiger/tests/mod.rs new file mode 100644 index 000000000..6f2cca17f --- /dev/null +++ b/tiger/tests/mod.rs @@ -0,0 +1,4 @@ +use digest::{dev::digest_test, new_test}; + +new_test!(tiger, "tiger", tiger::Tiger, digest_test); +new_test!(tiger2, "tiger2", tiger::Tiger2, digest_test); diff --git a/whirlpool/CHANGELOG.md b/whirlpool/CHANGELOG.md index 2d3c97dfd..0c34ef2f9 100644 --- a/whirlpool/CHANGELOG.md +++ b/whirlpool/CHANGELOG.md @@ -5,6 +5,12 @@ 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). +## 0.10.0 (2021-11-22) +### Changed +- Update to `digest` v0.10 ([#217]) + +[#217]: https://github.com/RustCrypto/hashes/pull/217 + ## 0.9.0 (2020-06-12) ### Changed - Bump `opaque-debug` to v0.3.0 ([#168]) diff --git a/whirlpool/Cargo.toml b/whirlpool/Cargo.toml index 395ed8a3c..777785c4a 100644 --- a/whirlpool/Cargo.toml +++ b/whirlpool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "whirlpool" -version = "0.9.0" +version = "0.10.0" # Also update html_root_url in lib.rs when bumping this description = "Whirlpool hash function" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -12,13 +12,11 @@ keywords = ["crypto", "whirlpool", "hash", "digest"] categories = ["cryptography", "no-std"] [dependencies] -digest = "0.9" -block-buffer = { version = "0.9", features = ["block-padding"] } -opaque-debug = "0.3" -whirlpool-asm = { version = "0.5", optional = true } +digest = "0.10" +whirlpool-asm = { version = "0.6", optional = true} [dev-dependencies] -digest = { version = "0.9", features = ["dev"] } +digest = { version = "0.10", features = ["dev"] } hex-literal = "0.2" [features] diff --git a/whirlpool/examples/whirlpool_sum.rs b/whirlpool/examples/whirlpool_sum.rs deleted file mode 100644 index fe2416b8f..000000000 --- a/whirlpool/examples/whirlpool_sum.rs +++ /dev/null @@ -1,47 +0,0 @@ -use std::env; -use std::fs; -use std::io::{self, Read}; -use whirlpool::{Digest, Whirlpool}; - -const BUFFER_SIZE: usize = 1024; - -/// Print digest result as hex string and name pair -fn print_result(sum: &[u8], name: &str) { - for byte in sum { - print!("{:02x}", byte); - } - println!("\t{}", name); -} - -/// Compute digest value for given `Reader` and print it -/// On any error simply return without doing anything -fn process(reader: &mut R, name: &str) { - let mut sh: D = Default::default(); - let mut buffer = [0u8; BUFFER_SIZE]; - loop { - let n = match reader.read(&mut buffer) { - Ok(n) => n, - Err(_) => return, - }; - sh.update(&buffer[..n]); - if n == 0 || n < BUFFER_SIZE { - break; - } - } - print_result(&sh.finalize(), name); -} - -fn main() { - let args = env::args(); - // Process files listed in command line arguments one by one - // If no files provided process input from stdin - if args.len() > 1 { - for path in args.skip(1) { - if let Ok(mut file) = fs::File::open(&path) { - process::(&mut file, &path); - } - } - } else { - process::(&mut io::stdin(), "-"); - } -} diff --git a/whirlpool/src/compress.rs b/whirlpool/src/compress.rs new file mode 100644 index 000000000..4f1664e30 --- /dev/null +++ b/whirlpool/src/compress.rs @@ -0,0 +1,60 @@ +use crate::BLOCK_SIZE; +use core::convert::TryInto; + +#[path = "consts.rs"] +mod consts; +use consts::*; + +fn compress_block(state: &mut [u64; 8], b: &[u8; BLOCK_SIZE]) { + let mut k = [0u64; 8]; + let mut block = [0u64; 8]; + let mut s = [0u64; 8]; + let mut l = [0u64; 8]; + + for (o, chunk) in block.iter_mut().zip(b.chunks_exact(8)) { + *o = u64::from_le_bytes(chunk.try_into().unwrap()); + } + k.copy_from_slice(state); + + for i in 0..8 { + s[i] = block[i] ^ k[i]; + } + + #[allow(clippy::needless_range_loop)] + for r in 0..R { + for i in 0..8 { + l[i] = C0[(k[(i) % 8] & 0xff) as usize] + ^ C1[((k[(7 + i) % 8] >> 8) & 0xff) as usize] + ^ C2[((k[(6 + i) % 8] >> 16) & 0xff) as usize] + ^ C3[((k[(5 + i) % 8] >> 24) & 0xff) as usize] + ^ C4[((k[(4 + i) % 8] >> 32) & 0xff) as usize] + ^ C5[((k[(3 + i) % 8] >> 40) & 0xff) as usize] + ^ C6[((k[(2 + i) % 8] >> 48) & 0xff) as usize] + ^ C7[((k[(1 + i) % 8] >> 56) & 0xff) as usize] + ^ if i == 0 { RC[r] } else { 0 }; + } + k = l; + for i in 0..8 { + l[i] = C0[(s[(i) % 8] & 0xff) as usize] + ^ C1[((s[(7 + i) % 8] >> 8) & 0xff) as usize] + ^ C2[((s[(6 + i) % 8] >> 16) & 0xff) as usize] + ^ C3[((s[(5 + i) % 8] >> 24) & 0xff) as usize] + ^ C4[((s[(4 + i) % 8] >> 32) & 0xff) as usize] + ^ C5[((s[(3 + i) % 8] >> 40) & 0xff) as usize] + ^ C6[((s[(2 + i) % 8] >> 48) & 0xff) as usize] + ^ C7[((s[(1 + i) % 8] >> 56) & 0xff) as usize] + ^ k[i]; + } + s = l; + } + + for i in 0..8 { + state[i] ^= s[i] ^ block[i]; + } +} + +pub(crate) fn compress(state: &mut [u64; 8], blocks: &[[u8; BLOCK_SIZE]]) { + for block in blocks { + compress_block(state, block); + } +} diff --git a/whirlpool/src/consts.rs b/whirlpool/src/consts.rs index aad56c63e..756437d21 100644 --- a/whirlpool/src/consts.rs +++ b/whirlpool/src/consts.rs @@ -1,2089 +1,2088 @@ #![allow(clippy::unreadable_literal)] -pub static R: usize = 10; +pub const R: usize = 10; -pub static RC: [u64; 11 /* R + 1 */] = [ - 0x0000000000000000, - 0x1823c6e887b8014f, - 0x36a6d2f5796f9152, - 0x60bc9b8ea30c7b35, - 0x1de0d7c22e4bfe57, - 0x157737e59ff04ada, - 0x58c9290ab1a06b85, - 0xbd5d10f4cb3e0567, - 0xe427418ba77d95d8, - 0xfbee7c66dd17479e, - 0xca2dbf07ad5a8333, +pub const RC: [u64; R] = [ + 0x4f01b887e8c62318, + 0x52916f79f5d2a636, + 0x357b0ca38e9bbc60, + 0x57fe4b2ec2d7e01d, + 0xda4af09fe5377715, + 0x856ba0b10a29c958, + 0x67053ecbf4105dbd, + 0xd8957da78b4127e4, + 0x9e4717dd667ceefb, + 0x33835aad07bf2dca, ]; -pub static C0: [u64; 256] = [ - 0x18186018c07830d8, - 0x23238c2305af4626, - 0xc6c63fc67ef991b8, - 0xe8e887e8136fcdfb, - 0x878726874ca113cb, - 0xb8b8dab8a9626d11, - 0x0101040108050209, - 0x4f4f214f426e9e0d, - 0x3636d836adee6c9b, - 0xa6a6a2a6590451ff, - 0xd2d26fd2debdb90c, - 0xf5f5f3f5fb06f70e, - 0x7979f979ef80f296, - 0x6f6fa16f5fcede30, - 0x91917e91fcef3f6d, - 0x52525552aa07a4f8, - 0x60609d6027fdc047, - 0xbcbccabc89766535, - 0x9b9b569baccd2b37, - 0x8e8e028e048c018a, - 0xa3a3b6a371155bd2, - 0x0c0c300c603c186c, - 0x7b7bf17bff8af684, - 0x3535d435b5e16a80, - 0x1d1d741de8693af5, - 0xe0e0a7e05347ddb3, - 0xd7d77bd7f6acb321, - 0xc2c22fc25eed999c, - 0x2e2eb82e6d965c43, - 0x4b4b314b627a9629, - 0xfefedffea321e15d, - 0x575741578216aed5, - 0x15155415a8412abd, - 0x7777c1779fb6eee8, - 0x3737dc37a5eb6e92, - 0xe5e5b3e57b56d79e, - 0x9f9f469f8cd92313, - 0xf0f0e7f0d317fd23, - 0x4a4a354a6a7f9420, - 0xdada4fda9e95a944, - 0x58587d58fa25b0a2, - 0xc9c903c906ca8fcf, - 0x2929a429558d527c, - 0x0a0a280a5022145a, - 0xb1b1feb1e14f7f50, - 0xa0a0baa0691a5dc9, - 0x6b6bb16b7fdad614, - 0x85852e855cab17d9, - 0xbdbdcebd8173673c, - 0x5d5d695dd234ba8f, - 0x1010401080502090, - 0xf4f4f7f4f303f507, - 0xcbcb0bcb16c08bdd, - 0x3e3ef83eedc67cd3, - 0x0505140528110a2d, - 0x676781671fe6ce78, - 0xe4e4b7e47353d597, - 0x27279c2725bb4e02, - 0x4141194132588273, - 0x8b8b168b2c9d0ba7, - 0xa7a7a6a7510153f6, - 0x7d7de97dcf94fab2, - 0x95956e95dcfb3749, - 0xd8d847d88e9fad56, - 0xfbfbcbfb8b30eb70, - 0xeeee9fee2371c1cd, - 0x7c7ced7cc791f8bb, - 0x6666856617e3cc71, - 0xdddd53dda68ea77b, - 0x17175c17b84b2eaf, - 0x4747014702468e45, - 0x9e9e429e84dc211a, - 0xcaca0fca1ec589d4, - 0x2d2db42d75995a58, - 0xbfbfc6bf9179632e, - 0x07071c07381b0e3f, - 0xadad8ead012347ac, - 0x5a5a755aea2fb4b0, - 0x838336836cb51bef, - 0x3333cc3385ff66b6, - 0x636391633ff2c65c, - 0x02020802100a0412, - 0xaaaa92aa39384993, - 0x7171d971afa8e2de, - 0xc8c807c80ecf8dc6, - 0x19196419c87d32d1, - 0x494939497270923b, - 0xd9d943d9869aaf5f, - 0xf2f2eff2c31df931, - 0xe3e3abe34b48dba8, - 0x5b5b715be22ab6b9, - 0x88881a8834920dbc, - 0x9a9a529aa4c8293e, - 0x262698262dbe4c0b, - 0x3232c8328dfa64bf, - 0xb0b0fab0e94a7d59, - 0xe9e983e91b6acff2, - 0x0f0f3c0f78331e77, - 0xd5d573d5e6a6b733, - 0x80803a8074ba1df4, - 0xbebec2be997c6127, - 0xcdcd13cd26de87eb, - 0x3434d034bde46889, - 0x48483d487a759032, - 0xffffdbffab24e354, - 0x7a7af57af78ff48d, - 0x90907a90f4ea3d64, - 0x5f5f615fc23ebe9d, - 0x202080201da0403d, - 0x6868bd6867d5d00f, - 0x1a1a681ad07234ca, - 0xaeae82ae192c41b7, - 0xb4b4eab4c95e757d, - 0x54544d549a19a8ce, - 0x93937693ece53b7f, - 0x222288220daa442f, - 0x64648d6407e9c863, - 0xf1f1e3f1db12ff2a, - 0x7373d173bfa2e6cc, - 0x12124812905a2482, - 0x40401d403a5d807a, - 0x0808200840281048, - 0xc3c32bc356e89b95, - 0xecec97ec337bc5df, - 0xdbdb4bdb9690ab4d, - 0xa1a1bea1611f5fc0, - 0x8d8d0e8d1c830791, - 0x3d3df43df5c97ac8, - 0x97976697ccf1335b, +pub const C0: [u64; 256] = [ + 0xd83078c018601818, + 0x2646af05238c2323, + 0xb891f97ec63fc6c6, + 0xfbcd6f13e887e8e8, + 0xcb13a14c87268787, + 0x116d62a9b8dab8b8, + 0x0902050801040101, + 0x0d9e6e424f214f4f, + 0x9b6ceead36d83636, + 0xff510459a6a2a6a6, + 0x0cb9bdded26fd2d2, + 0x0ef706fbf5f3f5f5, + 0x96f280ef79f97979, + 0x30dece5f6fa16f6f, + 0x6d3feffc917e9191, + 0xf8a407aa52555252, + 0x47c0fd27609d6060, + 0x35657689bccabcbc, + 0x372bcdac9b569b9b, + 0x8a018c048e028e8e, + 0xd25b1571a3b6a3a3, + 0x6c183c600c300c0c, + 0x84f68aff7bf17b7b, + 0x806ae1b535d43535, + 0xf53a69e81d741d1d, + 0xb3dd4753e0a7e0e0, + 0x21b3acf6d77bd7d7, + 0x9c99ed5ec22fc2c2, + 0x435c966d2eb82e2e, + 0x29967a624b314b4b, + 0x5de121a3fedffefe, + 0xd5ae168257415757, + 0xbd2a41a815541515, + 0xe8eeb69f77c17777, + 0x926eeba537dc3737, + 0x9ed7567be5b3e5e5, + 0x1323d98c9f469f9f, + 0x23fd17d3f0e7f0f0, + 0x20947f6a4a354a4a, + 0x44a9959eda4fdada, + 0xa2b025fa587d5858, + 0xcf8fca06c903c9c9, + 0x7c528d5529a42929, + 0x5a1422500a280a0a, + 0x507f4fe1b1feb1b1, + 0xc95d1a69a0baa0a0, + 0x14d6da7f6bb16b6b, + 0xd917ab5c852e8585, + 0x3c677381bdcebdbd, + 0x8fba34d25d695d5d, + 0x9020508010401010, + 0x07f503f3f4f7f4f4, + 0xdd8bc016cb0bcbcb, + 0xd37cc6ed3ef83e3e, + 0x2d0a112805140505, + 0x78cee61f67816767, + 0x97d55373e4b7e4e4, + 0x024ebb25279c2727, + 0x7382583241194141, + 0xa70b9d2c8b168b8b, + 0xf6530151a7a6a7a7, + 0xb2fa94cf7de97d7d, + 0x4937fbdc956e9595, + 0x56ad9f8ed847d8d8, + 0x70eb308bfbcbfbfb, + 0xcdc17123ee9feeee, + 0xbbf891c77ced7c7c, + 0x71cce31766856666, + 0x7ba78ea6dd53dddd, + 0xaf2e4bb8175c1717, + 0x458e460247014747, + 0x1a21dc849e429e9e, + 0xd489c51eca0fcaca, + 0x585a99752db42d2d, + 0x2e637991bfc6bfbf, + 0x3f0e1b38071c0707, + 0xac472301ad8eadad, + 0xb0b42fea5a755a5a, + 0xef1bb56c83368383, + 0xb666ff8533cc3333, + 0x5cc6f23f63916363, + 0x12040a1002080202, + 0x93493839aa92aaaa, + 0xdee2a8af71d97171, + 0xc68dcf0ec807c8c8, + 0xd1327dc819641919, + 0x3b92707249394949, + 0x5faf9a86d943d9d9, + 0x31f91dc3f2eff2f2, + 0xa8db484be3abe3e3, + 0xb9b62ae25b715b5b, + 0xbc0d9234881a8888, + 0x3e29c8a49a529a9a, + 0x0b4cbe2d26982626, + 0xbf64fa8d32c83232, + 0x597d4ae9b0fab0b0, + 0xf2cf6a1be983e9e9, + 0x771e33780f3c0f0f, + 0x33b7a6e6d573d5d5, + 0xf41dba74803a8080, + 0x27617c99bec2bebe, + 0xeb87de26cd13cdcd, + 0x8968e4bd34d03434, + 0x3290757a483d4848, + 0x54e324abffdbffff, + 0x8df48ff77af57a7a, + 0x643deaf4907a9090, + 0x9dbe3ec25f615f5f, + 0x3d40a01d20802020, + 0x0fd0d56768bd6868, + 0xca3472d01a681a1a, + 0xb7412c19ae82aeae, + 0x7d755ec9b4eab4b4, + 0xcea8199a544d5454, + 0x7f3be5ec93769393, + 0x2f44aa0d22882222, + 0x63c8e907648d6464, + 0x2aff12dbf1e3f1f1, + 0xcce6a2bf73d17373, + 0x82245a9012481212, + 0x7a805d3a401d4040, + 0x4810284008200808, + 0x959be856c32bc3c3, + 0xdfc57b33ec97ecec, + 0x4dab9096db4bdbdb, + 0xc05f1f61a1bea1a1, + 0x9107831c8d0e8d8d, + 0xc87ac9f53df43d3d, + 0x5b33f1cc97669797, 0x0000000000000000, - 0xcfcf1bcf36d483f9, - 0x2b2bac2b4587566e, - 0x7676c57697b3ece1, - 0x8282328264b019e6, - 0xd6d67fd6fea9b128, - 0x1b1b6c1bd87736c3, - 0xb5b5eeb5c15b7774, - 0xafaf86af112943be, - 0x6a6ab56a77dfd41d, - 0x50505d50ba0da0ea, - 0x45450945124c8a57, - 0xf3f3ebf3cb18fb38, - 0x3030c0309df060ad, - 0xefef9bef2b74c3c4, - 0x3f3ffc3fe5c37eda, - 0x55554955921caac7, - 0xa2a2b2a2791059db, - 0xeaea8fea0365c9e9, - 0x656589650fecca6a, - 0xbabad2bab9686903, - 0x2f2fbc2f65935e4a, - 0xc0c027c04ee79d8e, - 0xdede5fdebe81a160, - 0x1c1c701ce06c38fc, - 0xfdfdd3fdbb2ee746, - 0x4d4d294d52649a1f, - 0x92927292e4e03976, - 0x7575c9758fbceafa, - 0x06061806301e0c36, - 0x8a8a128a249809ae, - 0xb2b2f2b2f940794b, - 0xe6e6bfe66359d185, - 0x0e0e380e70361c7e, - 0x1f1f7c1ff8633ee7, - 0x6262956237f7c455, - 0xd4d477d4eea3b53a, - 0xa8a89aa829324d81, - 0x96966296c4f43152, - 0xf9f9c3f99b3aef62, - 0xc5c533c566f697a3, - 0x2525942535b14a10, - 0x59597959f220b2ab, - 0x84842a8454ae15d0, - 0x7272d572b7a7e4c5, - 0x3939e439d5dd72ec, - 0x4c4c2d4c5a619816, - 0x5e5e655eca3bbc94, - 0x7878fd78e785f09f, - 0x3838e038ddd870e5, - 0x8c8c0a8c14860598, - 0xd1d163d1c6b2bf17, - 0xa5a5aea5410b57e4, - 0xe2e2afe2434dd9a1, - 0x616199612ff8c24e, - 0xb3b3f6b3f1457b42, - 0x2121842115a54234, - 0x9c9c4a9c94d62508, - 0x1e1e781ef0663cee, - 0x4343114322528661, - 0xc7c73bc776fc93b1, - 0xfcfcd7fcb32be54f, - 0x0404100420140824, - 0x51515951b208a2e3, - 0x99995e99bcc72f25, - 0x6d6da96d4fc4da22, - 0x0d0d340d68391a65, - 0xfafacffa8335e979, - 0xdfdf5bdfb684a369, - 0x7e7ee57ed79bfca9, - 0x242490243db44819, - 0x3b3bec3bc5d776fe, - 0xabab96ab313d4b9a, - 0xcece1fce3ed181f0, - 0x1111441188552299, - 0x8f8f068f0c890383, - 0x4e4e254e4a6b9c04, - 0xb7b7e6b7d1517366, - 0xebeb8beb0b60cbe0, - 0x3c3cf03cfdcc78c1, - 0x81813e817cbf1ffd, - 0x94946a94d4fe3540, - 0xf7f7fbf7eb0cf31c, - 0xb9b9deb9a1676f18, - 0x13134c13985f268b, - 0x2c2cb02c7d9c5851, - 0xd3d36bd3d6b8bb05, - 0xe7e7bbe76b5cd38c, - 0x6e6ea56e57cbdc39, - 0xc4c437c46ef395aa, - 0x03030c03180f061b, - 0x565645568a13acdc, - 0x44440d441a49885e, - 0x7f7fe17fdf9efea0, - 0xa9a99ea921374f88, - 0x2a2aa82a4d825467, - 0xbbbbd6bbb16d6b0a, - 0xc1c123c146e29f87, - 0x53535153a202a6f1, - 0xdcdc57dcae8ba572, - 0x0b0b2c0b58271653, - 0x9d9d4e9d9cd32701, - 0x6c6cad6c47c1d82b, - 0x3131c43195f562a4, - 0x7474cd7487b9e8f3, - 0xf6f6fff6e309f115, - 0x464605460a438c4c, - 0xacac8aac092645a5, - 0x89891e893c970fb5, - 0x14145014a04428b4, - 0xe1e1a3e15b42dfba, - 0x16165816b04e2ca6, - 0x3a3ae83acdd274f7, - 0x6969b9696fd0d206, - 0x09092409482d1241, - 0x7070dd70a7ade0d7, - 0xb6b6e2b6d954716f, - 0xd0d067d0ceb7bd1e, - 0xeded93ed3b7ec7d6, - 0xcccc17cc2edb85e2, - 0x424215422a578468, - 0x98985a98b4c22d2c, - 0xa4a4aaa4490e55ed, - 0x2828a0285d885075, - 0x5c5c6d5cda31b886, - 0xf8f8c7f8933fed6b, - 0x8686228644a411c2, + 0xf983d436cf1bcfcf, + 0x6e5687452bac2b2b, + 0xe1ecb39776c57676, + 0xe619b06482328282, + 0x28b1a9fed67fd6d6, + 0xc33677d81b6c1b1b, + 0x74775bc1b5eeb5b5, + 0xbe432911af86afaf, + 0x1dd4df776ab56a6a, + 0xeaa00dba505d5050, + 0x578a4c1245094545, + 0x38fb18cbf3ebf3f3, + 0xad60f09d30c03030, + 0xc4c3742bef9befef, + 0xda7ec3e53ffc3f3f, + 0xc7aa1c9255495555, + 0xdb591079a2b2a2a2, + 0xe9c96503ea8feaea, + 0x6acaec0f65896565, + 0x036968b9bad2baba, + 0x4a5e93652fbc2f2f, + 0x8e9de74ec027c0c0, + 0x60a181bede5fdede, + 0xfc386ce01c701c1c, + 0x46e72ebbfdd3fdfd, + 0x1f9a64524d294d4d, + 0x7639e0e492729292, + 0xfaeabc8f75c97575, + 0x360c1e3006180606, + 0xae0998248a128a8a, + 0x4b7940f9b2f2b2b2, + 0x85d15963e6bfe6e6, + 0x7e1c36700e380e0e, + 0xe73e63f81f7c1f1f, + 0x55c4f73762956262, + 0x3ab5a3eed477d4d4, + 0x814d3229a89aa8a8, + 0x5231f4c496629696, + 0x62ef3a9bf9c3f9f9, + 0xa397f666c533c5c5, + 0x104ab13525942525, + 0xabb220f259795959, + 0xd015ae54842a8484, + 0xc5e4a7b772d57272, + 0xec72ddd539e43939, + 0x1698615a4c2d4c4c, + 0x94bc3bca5e655e5e, + 0x9ff085e778fd7878, + 0xe570d8dd38e03838, + 0x980586148c0a8c8c, + 0x17bfb2c6d163d1d1, + 0xe4570b41a5aea5a5, + 0xa1d94d43e2afe2e2, + 0x4ec2f82f61996161, + 0x427b45f1b3f6b3b3, + 0x3442a51521842121, + 0x0825d6949c4a9c9c, + 0xee3c66f01e781e1e, + 0x6186522243114343, + 0xb193fc76c73bc7c7, + 0x4fe52bb3fcd7fcfc, + 0x2408142004100404, + 0xe3a208b251595151, + 0x252fc7bc995e9999, + 0x22dac44f6da96d6d, + 0x651a39680d340d0d, + 0x79e93583facffafa, + 0x69a384b6df5bdfdf, + 0xa9fc9bd77ee57e7e, + 0x1948b43d24902424, + 0xfe76d7c53bec3b3b, + 0x9a4b3d31ab96abab, + 0xf081d13ece1fcece, + 0x9922558811441111, + 0x8303890c8f068f8f, + 0x049c6b4a4e254e4e, + 0x667351d1b7e6b7b7, + 0xe0cb600beb8bebeb, + 0xc178ccfd3cf03c3c, + 0xfd1fbf7c813e8181, + 0x4035fed4946a9494, + 0x1cf30cebf7fbf7f7, + 0x186f67a1b9deb9b9, + 0x8b265f98134c1313, + 0x51589c7d2cb02c2c, + 0x05bbb8d6d36bd3d3, + 0x8cd35c6be7bbe7e7, + 0x39dccb576ea56e6e, + 0xaa95f36ec437c4c4, + 0x1b060f18030c0303, + 0xdcac138a56455656, + 0x5e88491a440d4444, + 0xa0fe9edf7fe17f7f, + 0x884f3721a99ea9a9, + 0x6754824d2aa82a2a, + 0x0a6b6db1bbd6bbbb, + 0x879fe246c123c1c1, + 0xf1a602a253515353, + 0x72a58baedc57dcdc, + 0x531627580b2c0b0b, + 0x0127d39c9d4e9d9d, + 0x2bd8c1476cad6c6c, + 0xa462f59531c43131, + 0xf3e8b98774cd7474, + 0x15f109e3f6fff6f6, + 0x4c8c430a46054646, + 0xa5452609ac8aacac, + 0xb50f973c891e8989, + 0xb42844a014501414, + 0xbadf425be1a3e1e1, + 0xa62c4eb016581616, + 0xf774d2cd3ae83a3a, + 0x06d2d06f69b96969, + 0x41122d4809240909, + 0xd7e0ada770dd7070, + 0x6f7154d9b6e2b6b6, + 0x1ebdb7ced067d0d0, + 0xd6c77e3bed93eded, + 0xe285db2ecc17cccc, + 0x6884572a42154242, + 0x2c2dc2b4985a9898, + 0xed550e49a4aaa4a4, + 0x7550885d28a02828, + 0x86b831da5c6d5c5c, + 0x6bed3f93f8c7f8f8, + 0xc211a44486228686, ]; -pub static C1: [u64; 256] = [ - 0xd818186018c07830, - 0x2623238c2305af46, - 0xb8c6c63fc67ef991, - 0xfbe8e887e8136fcd, - 0xcb878726874ca113, - 0x11b8b8dab8a9626d, - 0x0901010401080502, - 0x0d4f4f214f426e9e, - 0x9b3636d836adee6c, - 0xffa6a6a2a6590451, - 0x0cd2d26fd2debdb9, - 0x0ef5f5f3f5fb06f7, - 0x967979f979ef80f2, - 0x306f6fa16f5fcede, - 0x6d91917e91fcef3f, - 0xf852525552aa07a4, - 0x4760609d6027fdc0, - 0x35bcbccabc897665, - 0x379b9b569baccd2b, - 0x8a8e8e028e048c01, - 0xd2a3a3b6a371155b, - 0x6c0c0c300c603c18, - 0x847b7bf17bff8af6, - 0x803535d435b5e16a, - 0xf51d1d741de8693a, - 0xb3e0e0a7e05347dd, - 0x21d7d77bd7f6acb3, - 0x9cc2c22fc25eed99, - 0x432e2eb82e6d965c, - 0x294b4b314b627a96, - 0x5dfefedffea321e1, - 0xd5575741578216ae, - 0xbd15155415a8412a, - 0xe87777c1779fb6ee, - 0x923737dc37a5eb6e, - 0x9ee5e5b3e57b56d7, - 0x139f9f469f8cd923, - 0x23f0f0e7f0d317fd, - 0x204a4a354a6a7f94, - 0x44dada4fda9e95a9, - 0xa258587d58fa25b0, - 0xcfc9c903c906ca8f, - 0x7c2929a429558d52, - 0x5a0a0a280a502214, - 0x50b1b1feb1e14f7f, - 0xc9a0a0baa0691a5d, - 0x146b6bb16b7fdad6, - 0xd985852e855cab17, - 0x3cbdbdcebd817367, - 0x8f5d5d695dd234ba, - 0x9010104010805020, - 0x07f4f4f7f4f303f5, - 0xddcbcb0bcb16c08b, - 0xd33e3ef83eedc67c, - 0x2d0505140528110a, - 0x78676781671fe6ce, - 0x97e4e4b7e47353d5, - 0x0227279c2725bb4e, - 0x7341411941325882, - 0xa78b8b168b2c9d0b, - 0xf6a7a7a6a7510153, - 0xb27d7de97dcf94fa, - 0x4995956e95dcfb37, - 0x56d8d847d88e9fad, - 0x70fbfbcbfb8b30eb, - 0xcdeeee9fee2371c1, - 0xbb7c7ced7cc791f8, - 0x716666856617e3cc, - 0x7bdddd53dda68ea7, - 0xaf17175c17b84b2e, - 0x454747014702468e, - 0x1a9e9e429e84dc21, - 0xd4caca0fca1ec589, - 0x582d2db42d75995a, - 0x2ebfbfc6bf917963, - 0x3f07071c07381b0e, - 0xacadad8ead012347, - 0xb05a5a755aea2fb4, - 0xef838336836cb51b, - 0xb63333cc3385ff66, - 0x5c636391633ff2c6, - 0x1202020802100a04, - 0x93aaaa92aa393849, - 0xde7171d971afa8e2, - 0xc6c8c807c80ecf8d, - 0xd119196419c87d32, - 0x3b49493949727092, - 0x5fd9d943d9869aaf, - 0x31f2f2eff2c31df9, - 0xa8e3e3abe34b48db, - 0xb95b5b715be22ab6, - 0xbc88881a8834920d, - 0x3e9a9a529aa4c829, - 0x0b262698262dbe4c, - 0xbf3232c8328dfa64, - 0x59b0b0fab0e94a7d, - 0xf2e9e983e91b6acf, - 0x770f0f3c0f78331e, - 0x33d5d573d5e6a6b7, - 0xf480803a8074ba1d, - 0x27bebec2be997c61, - 0xebcdcd13cd26de87, - 0x893434d034bde468, - 0x3248483d487a7590, - 0x54ffffdbffab24e3, - 0x8d7a7af57af78ff4, - 0x6490907a90f4ea3d, - 0x9d5f5f615fc23ebe, - 0x3d202080201da040, - 0x0f6868bd6867d5d0, - 0xca1a1a681ad07234, - 0xb7aeae82ae192c41, - 0x7db4b4eab4c95e75, - 0xce54544d549a19a8, - 0x7f93937693ece53b, - 0x2f222288220daa44, - 0x6364648d6407e9c8, - 0x2af1f1e3f1db12ff, - 0xcc7373d173bfa2e6, - 0x8212124812905a24, - 0x7a40401d403a5d80, - 0x4808082008402810, - 0x95c3c32bc356e89b, - 0xdfecec97ec337bc5, - 0x4ddbdb4bdb9690ab, - 0xc0a1a1bea1611f5f, - 0x918d8d0e8d1c8307, - 0xc83d3df43df5c97a, - 0x5b97976697ccf133, +pub const C1: [u64; 256] = [ + 0x3078c018601818d8, + 0x46af05238c232326, + 0x91f97ec63fc6c6b8, + 0xcd6f13e887e8e8fb, + 0x13a14c87268787cb, + 0x6d62a9b8dab8b811, + 0x0205080104010109, + 0x9e6e424f214f4f0d, + 0x6ceead36d836369b, + 0x510459a6a2a6a6ff, + 0xb9bdded26fd2d20c, + 0xf706fbf5f3f5f50e, + 0xf280ef79f9797996, + 0xdece5f6fa16f6f30, + 0x3feffc917e91916d, + 0xa407aa52555252f8, + 0xc0fd27609d606047, + 0x657689bccabcbc35, + 0x2bcdac9b569b9b37, + 0x018c048e028e8e8a, + 0x5b1571a3b6a3a3d2, + 0x183c600c300c0c6c, + 0xf68aff7bf17b7b84, + 0x6ae1b535d4353580, + 0x3a69e81d741d1df5, + 0xdd4753e0a7e0e0b3, + 0xb3acf6d77bd7d721, + 0x99ed5ec22fc2c29c, + 0x5c966d2eb82e2e43, + 0x967a624b314b4b29, + 0xe121a3fedffefe5d, + 0xae168257415757d5, + 0x2a41a815541515bd, + 0xeeb69f77c17777e8, + 0x6eeba537dc373792, + 0xd7567be5b3e5e59e, + 0x23d98c9f469f9f13, + 0xfd17d3f0e7f0f023, + 0x947f6a4a354a4a20, + 0xa9959eda4fdada44, + 0xb025fa587d5858a2, + 0x8fca06c903c9c9cf, + 0x528d5529a429297c, + 0x1422500a280a0a5a, + 0x7f4fe1b1feb1b150, + 0x5d1a69a0baa0a0c9, + 0xd6da7f6bb16b6b14, + 0x17ab5c852e8585d9, + 0x677381bdcebdbd3c, + 0xba34d25d695d5d8f, + 0x2050801040101090, + 0xf503f3f4f7f4f407, + 0x8bc016cb0bcbcbdd, + 0x7cc6ed3ef83e3ed3, + 0x0a1128051405052d, + 0xcee61f6781676778, + 0xd55373e4b7e4e497, + 0x4ebb25279c272702, + 0x8258324119414173, + 0x0b9d2c8b168b8ba7, + 0x530151a7a6a7a7f6, + 0xfa94cf7de97d7db2, + 0x37fbdc956e959549, + 0xad9f8ed847d8d856, + 0xeb308bfbcbfbfb70, + 0xc17123ee9feeeecd, + 0xf891c77ced7c7cbb, + 0xcce3176685666671, + 0xa78ea6dd53dddd7b, + 0x2e4bb8175c1717af, + 0x8e46024701474745, + 0x21dc849e429e9e1a, + 0x89c51eca0fcacad4, + 0x5a99752db42d2d58, + 0x637991bfc6bfbf2e, + 0x0e1b38071c07073f, + 0x472301ad8eadadac, + 0xb42fea5a755a5ab0, + 0x1bb56c83368383ef, + 0x66ff8533cc3333b6, + 0xc6f23f639163635c, + 0x040a100208020212, + 0x493839aa92aaaa93, + 0xe2a8af71d97171de, + 0x8dcf0ec807c8c8c6, + 0x327dc819641919d1, + 0x927072493949493b, + 0xaf9a86d943d9d95f, + 0xf91dc3f2eff2f231, + 0xdb484be3abe3e3a8, + 0xb62ae25b715b5bb9, + 0x0d9234881a8888bc, + 0x29c8a49a529a9a3e, + 0x4cbe2d269826260b, + 0x64fa8d32c83232bf, + 0x7d4ae9b0fab0b059, + 0xcf6a1be983e9e9f2, + 0x1e33780f3c0f0f77, + 0xb7a6e6d573d5d533, + 0x1dba74803a8080f4, + 0x617c99bec2bebe27, + 0x87de26cd13cdcdeb, + 0x68e4bd34d0343489, + 0x90757a483d484832, + 0xe324abffdbffff54, + 0xf48ff77af57a7a8d, + 0x3deaf4907a909064, + 0xbe3ec25f615f5f9d, + 0x40a01d208020203d, + 0xd0d56768bd68680f, + 0x3472d01a681a1aca, + 0x412c19ae82aeaeb7, + 0x755ec9b4eab4b47d, + 0xa8199a544d5454ce, + 0x3be5ec937693937f, + 0x44aa0d228822222f, + 0xc8e907648d646463, + 0xff12dbf1e3f1f12a, + 0xe6a2bf73d17373cc, + 0x245a901248121282, + 0x805d3a401d40407a, + 0x1028400820080848, + 0x9be856c32bc3c395, + 0xc57b33ec97ececdf, + 0xab9096db4bdbdb4d, + 0x5f1f61a1bea1a1c0, + 0x07831c8d0e8d8d91, + 0x7ac9f53df43d3dc8, + 0x33f1cc976697975b, 0x0000000000000000, - 0xf9cfcf1bcf36d483, - 0x6e2b2bac2b458756, - 0xe17676c57697b3ec, - 0xe68282328264b019, - 0x28d6d67fd6fea9b1, - 0xc31b1b6c1bd87736, - 0x74b5b5eeb5c15b77, - 0xbeafaf86af112943, - 0x1d6a6ab56a77dfd4, - 0xea50505d50ba0da0, - 0x5745450945124c8a, - 0x38f3f3ebf3cb18fb, - 0xad3030c0309df060, - 0xc4efef9bef2b74c3, - 0xda3f3ffc3fe5c37e, - 0xc755554955921caa, - 0xdba2a2b2a2791059, - 0xe9eaea8fea0365c9, - 0x6a656589650fecca, - 0x03babad2bab96869, - 0x4a2f2fbc2f65935e, - 0x8ec0c027c04ee79d, - 0x60dede5fdebe81a1, - 0xfc1c1c701ce06c38, - 0x46fdfdd3fdbb2ee7, - 0x1f4d4d294d52649a, - 0x7692927292e4e039, - 0xfa7575c9758fbcea, - 0x3606061806301e0c, - 0xae8a8a128a249809, - 0x4bb2b2f2b2f94079, - 0x85e6e6bfe66359d1, - 0x7e0e0e380e70361c, - 0xe71f1f7c1ff8633e, - 0x556262956237f7c4, - 0x3ad4d477d4eea3b5, - 0x81a8a89aa829324d, - 0x5296966296c4f431, - 0x62f9f9c3f99b3aef, - 0xa3c5c533c566f697, - 0x102525942535b14a, - 0xab59597959f220b2, - 0xd084842a8454ae15, - 0xc57272d572b7a7e4, - 0xec3939e439d5dd72, - 0x164c4c2d4c5a6198, - 0x945e5e655eca3bbc, - 0x9f7878fd78e785f0, - 0xe53838e038ddd870, - 0x988c8c0a8c148605, - 0x17d1d163d1c6b2bf, - 0xe4a5a5aea5410b57, - 0xa1e2e2afe2434dd9, - 0x4e616199612ff8c2, - 0x42b3b3f6b3f1457b, - 0x342121842115a542, - 0x089c9c4a9c94d625, - 0xee1e1e781ef0663c, - 0x6143431143225286, - 0xb1c7c73bc776fc93, - 0x4ffcfcd7fcb32be5, - 0x2404041004201408, - 0xe351515951b208a2, - 0x2599995e99bcc72f, - 0x226d6da96d4fc4da, - 0x650d0d340d68391a, - 0x79fafacffa8335e9, - 0x69dfdf5bdfb684a3, - 0xa97e7ee57ed79bfc, - 0x19242490243db448, - 0xfe3b3bec3bc5d776, - 0x9aabab96ab313d4b, - 0xf0cece1fce3ed181, - 0x9911114411885522, - 0x838f8f068f0c8903, - 0x044e4e254e4a6b9c, - 0x66b7b7e6b7d15173, - 0xe0ebeb8beb0b60cb, - 0xc13c3cf03cfdcc78, - 0xfd81813e817cbf1f, - 0x4094946a94d4fe35, - 0x1cf7f7fbf7eb0cf3, - 0x18b9b9deb9a1676f, - 0x8b13134c13985f26, - 0x512c2cb02c7d9c58, - 0x05d3d36bd3d6b8bb, - 0x8ce7e7bbe76b5cd3, - 0x396e6ea56e57cbdc, - 0xaac4c437c46ef395, - 0x1b03030c03180f06, - 0xdc565645568a13ac, - 0x5e44440d441a4988, - 0xa07f7fe17fdf9efe, - 0x88a9a99ea921374f, - 0x672a2aa82a4d8254, - 0x0abbbbd6bbb16d6b, - 0x87c1c123c146e29f, - 0xf153535153a202a6, - 0x72dcdc57dcae8ba5, - 0x530b0b2c0b582716, - 0x019d9d4e9d9cd327, - 0x2b6c6cad6c47c1d8, - 0xa43131c43195f562, - 0xf37474cd7487b9e8, - 0x15f6f6fff6e309f1, - 0x4c464605460a438c, - 0xa5acac8aac092645, - 0xb589891e893c970f, - 0xb414145014a04428, - 0xbae1e1a3e15b42df, - 0xa616165816b04e2c, - 0xf73a3ae83acdd274, - 0x066969b9696fd0d2, - 0x4109092409482d12, - 0xd77070dd70a7ade0, - 0x6fb6b6e2b6d95471, - 0x1ed0d067d0ceb7bd, - 0xd6eded93ed3b7ec7, - 0xe2cccc17cc2edb85, - 0x68424215422a5784, - 0x2c98985a98b4c22d, - 0xeda4a4aaa4490e55, - 0x752828a0285d8850, - 0x865c5c6d5cda31b8, - 0x6bf8f8c7f8933fed, - 0xc28686228644a411, + 0x83d436cf1bcfcff9, + 0x5687452bac2b2b6e, + 0xecb39776c57676e1, + 0x19b06482328282e6, + 0xb1a9fed67fd6d628, + 0x3677d81b6c1b1bc3, + 0x775bc1b5eeb5b574, + 0x432911af86afafbe, + 0xd4df776ab56a6a1d, + 0xa00dba505d5050ea, + 0x8a4c124509454557, + 0xfb18cbf3ebf3f338, + 0x60f09d30c03030ad, + 0xc3742bef9befefc4, + 0x7ec3e53ffc3f3fda, + 0xaa1c9255495555c7, + 0x591079a2b2a2a2db, + 0xc96503ea8feaeae9, + 0xcaec0f658965656a, + 0x6968b9bad2baba03, + 0x5e93652fbc2f2f4a, + 0x9de74ec027c0c08e, + 0xa181bede5fdede60, + 0x386ce01c701c1cfc, + 0xe72ebbfdd3fdfd46, + 0x9a64524d294d4d1f, + 0x39e0e49272929276, + 0xeabc8f75c97575fa, + 0x0c1e300618060636, + 0x0998248a128a8aae, + 0x7940f9b2f2b2b24b, + 0xd15963e6bfe6e685, + 0x1c36700e380e0e7e, + 0x3e63f81f7c1f1fe7, + 0xc4f7376295626255, + 0xb5a3eed477d4d43a, + 0x4d3229a89aa8a881, + 0x31f4c49662969652, + 0xef3a9bf9c3f9f962, + 0x97f666c533c5c5a3, + 0x4ab1352594252510, + 0xb220f259795959ab, + 0x15ae54842a8484d0, + 0xe4a7b772d57272c5, + 0x72ddd539e43939ec, + 0x98615a4c2d4c4c16, + 0xbc3bca5e655e5e94, + 0xf085e778fd78789f, + 0x70d8dd38e03838e5, + 0x0586148c0a8c8c98, + 0xbfb2c6d163d1d117, + 0x570b41a5aea5a5e4, + 0xd94d43e2afe2e2a1, + 0xc2f82f619961614e, + 0x7b45f1b3f6b3b342, + 0x42a5152184212134, + 0x25d6949c4a9c9c08, + 0x3c66f01e781e1eee, + 0x8652224311434361, + 0x93fc76c73bc7c7b1, + 0xe52bb3fcd7fcfc4f, + 0x0814200410040424, + 0xa208b251595151e3, + 0x2fc7bc995e999925, + 0xdac44f6da96d6d22, + 0x1a39680d340d0d65, + 0xe93583facffafa79, + 0xa384b6df5bdfdf69, + 0xfc9bd77ee57e7ea9, + 0x48b43d2490242419, + 0x76d7c53bec3b3bfe, + 0x4b3d31ab96abab9a, + 0x81d13ece1fcecef0, + 0x2255881144111199, + 0x03890c8f068f8f83, + 0x9c6b4a4e254e4e04, + 0x7351d1b7e6b7b766, + 0xcb600beb8bebebe0, + 0x78ccfd3cf03c3cc1, + 0x1fbf7c813e8181fd, + 0x35fed4946a949440, + 0xf30cebf7fbf7f71c, + 0x6f67a1b9deb9b918, + 0x265f98134c13138b, + 0x589c7d2cb02c2c51, + 0xbbb8d6d36bd3d305, + 0xd35c6be7bbe7e78c, + 0xdccb576ea56e6e39, + 0x95f36ec437c4c4aa, + 0x060f18030c03031b, + 0xac138a56455656dc, + 0x88491a440d44445e, + 0xfe9edf7fe17f7fa0, + 0x4f3721a99ea9a988, + 0x54824d2aa82a2a67, + 0x6b6db1bbd6bbbb0a, + 0x9fe246c123c1c187, + 0xa602a253515353f1, + 0xa58baedc57dcdc72, + 0x1627580b2c0b0b53, + 0x27d39c9d4e9d9d01, + 0xd8c1476cad6c6c2b, + 0x62f59531c43131a4, + 0xe8b98774cd7474f3, + 0xf109e3f6fff6f615, + 0x8c430a460546464c, + 0x452609ac8aacaca5, + 0x0f973c891e8989b5, + 0x2844a014501414b4, + 0xdf425be1a3e1e1ba, + 0x2c4eb016581616a6, + 0x74d2cd3ae83a3af7, + 0xd2d06f69b9696906, + 0x122d480924090941, + 0xe0ada770dd7070d7, + 0x7154d9b6e2b6b66f, + 0xbdb7ced067d0d01e, + 0xc77e3bed93ededd6, + 0x85db2ecc17cccce2, + 0x84572a4215424268, + 0x2dc2b4985a98982c, + 0x550e49a4aaa4a4ed, + 0x50885d28a0282875, + 0xb831da5c6d5c5c86, + 0xed3f93f8c7f8f86b, + 0x11a44486228686c2, ]; -pub static C2: [u64; 256] = [ - 0x30d818186018c078, - 0x462623238c2305af, - 0x91b8c6c63fc67ef9, - 0xcdfbe8e887e8136f, - 0x13cb878726874ca1, - 0x6d11b8b8dab8a962, - 0x0209010104010805, - 0x9e0d4f4f214f426e, - 0x6c9b3636d836adee, - 0x51ffa6a6a2a65904, - 0xb90cd2d26fd2debd, - 0xf70ef5f5f3f5fb06, - 0xf2967979f979ef80, - 0xde306f6fa16f5fce, - 0x3f6d91917e91fcef, - 0xa4f852525552aa07, - 0xc04760609d6027fd, - 0x6535bcbccabc8976, - 0x2b379b9b569baccd, - 0x018a8e8e028e048c, - 0x5bd2a3a3b6a37115, - 0x186c0c0c300c603c, - 0xf6847b7bf17bff8a, - 0x6a803535d435b5e1, - 0x3af51d1d741de869, - 0xddb3e0e0a7e05347, - 0xb321d7d77bd7f6ac, - 0x999cc2c22fc25eed, - 0x5c432e2eb82e6d96, - 0x96294b4b314b627a, - 0xe15dfefedffea321, - 0xaed5575741578216, - 0x2abd15155415a841, - 0xeee87777c1779fb6, - 0x6e923737dc37a5eb, - 0xd79ee5e5b3e57b56, - 0x23139f9f469f8cd9, - 0xfd23f0f0e7f0d317, - 0x94204a4a354a6a7f, - 0xa944dada4fda9e95, - 0xb0a258587d58fa25, - 0x8fcfc9c903c906ca, - 0x527c2929a429558d, - 0x145a0a0a280a5022, - 0x7f50b1b1feb1e14f, - 0x5dc9a0a0baa0691a, - 0xd6146b6bb16b7fda, - 0x17d985852e855cab, - 0x673cbdbdcebd8173, - 0xba8f5d5d695dd234, - 0x2090101040108050, - 0xf507f4f4f7f4f303, - 0x8bddcbcb0bcb16c0, - 0x7cd33e3ef83eedc6, - 0x0a2d050514052811, - 0xce78676781671fe6, - 0xd597e4e4b7e47353, - 0x4e0227279c2725bb, - 0x8273414119413258, - 0x0ba78b8b168b2c9d, - 0x53f6a7a7a6a75101, - 0xfab27d7de97dcf94, - 0x374995956e95dcfb, - 0xad56d8d847d88e9f, - 0xeb70fbfbcbfb8b30, - 0xc1cdeeee9fee2371, - 0xf8bb7c7ced7cc791, - 0xcc716666856617e3, - 0xa77bdddd53dda68e, - 0x2eaf17175c17b84b, - 0x8e45474701470246, - 0x211a9e9e429e84dc, - 0x89d4caca0fca1ec5, - 0x5a582d2db42d7599, - 0x632ebfbfc6bf9179, - 0x0e3f07071c07381b, - 0x47acadad8ead0123, - 0xb4b05a5a755aea2f, - 0x1bef838336836cb5, - 0x66b63333cc3385ff, - 0xc65c636391633ff2, - 0x041202020802100a, - 0x4993aaaa92aa3938, - 0xe2de7171d971afa8, - 0x8dc6c8c807c80ecf, - 0x32d119196419c87d, - 0x923b494939497270, - 0xaf5fd9d943d9869a, - 0xf931f2f2eff2c31d, - 0xdba8e3e3abe34b48, - 0xb6b95b5b715be22a, - 0x0dbc88881a883492, - 0x293e9a9a529aa4c8, - 0x4c0b262698262dbe, - 0x64bf3232c8328dfa, - 0x7d59b0b0fab0e94a, - 0xcff2e9e983e91b6a, - 0x1e770f0f3c0f7833, - 0xb733d5d573d5e6a6, - 0x1df480803a8074ba, - 0x6127bebec2be997c, - 0x87ebcdcd13cd26de, - 0x68893434d034bde4, - 0x903248483d487a75, - 0xe354ffffdbffab24, - 0xf48d7a7af57af78f, - 0x3d6490907a90f4ea, - 0xbe9d5f5f615fc23e, - 0x403d202080201da0, - 0xd00f6868bd6867d5, - 0x34ca1a1a681ad072, - 0x41b7aeae82ae192c, - 0x757db4b4eab4c95e, - 0xa8ce54544d549a19, - 0x3b7f93937693ece5, - 0x442f222288220daa, - 0xc86364648d6407e9, - 0xff2af1f1e3f1db12, - 0xe6cc7373d173bfa2, - 0x248212124812905a, - 0x807a40401d403a5d, - 0x1048080820084028, - 0x9b95c3c32bc356e8, - 0xc5dfecec97ec337b, - 0xab4ddbdb4bdb9690, - 0x5fc0a1a1bea1611f, - 0x07918d8d0e8d1c83, - 0x7ac83d3df43df5c9, - 0x335b97976697ccf1, +pub const C2: [u64; 256] = [ + 0x78c018601818d830, + 0xaf05238c23232646, + 0xf97ec63fc6c6b891, + 0x6f13e887e8e8fbcd, + 0xa14c87268787cb13, + 0x62a9b8dab8b8116d, + 0x0508010401010902, + 0x6e424f214f4f0d9e, + 0xeead36d836369b6c, + 0x0459a6a2a6a6ff51, + 0xbdded26fd2d20cb9, + 0x06fbf5f3f5f50ef7, + 0x80ef79f9797996f2, + 0xce5f6fa16f6f30de, + 0xeffc917e91916d3f, + 0x07aa52555252f8a4, + 0xfd27609d606047c0, + 0x7689bccabcbc3565, + 0xcdac9b569b9b372b, + 0x8c048e028e8e8a01, + 0x1571a3b6a3a3d25b, + 0x3c600c300c0c6c18, + 0x8aff7bf17b7b84f6, + 0xe1b535d43535806a, + 0x69e81d741d1df53a, + 0x4753e0a7e0e0b3dd, + 0xacf6d77bd7d721b3, + 0xed5ec22fc2c29c99, + 0x966d2eb82e2e435c, + 0x7a624b314b4b2996, + 0x21a3fedffefe5de1, + 0x168257415757d5ae, + 0x41a815541515bd2a, + 0xb69f77c17777e8ee, + 0xeba537dc3737926e, + 0x567be5b3e5e59ed7, + 0xd98c9f469f9f1323, + 0x17d3f0e7f0f023fd, + 0x7f6a4a354a4a2094, + 0x959eda4fdada44a9, + 0x25fa587d5858a2b0, + 0xca06c903c9c9cf8f, + 0x8d5529a429297c52, + 0x22500a280a0a5a14, + 0x4fe1b1feb1b1507f, + 0x1a69a0baa0a0c95d, + 0xda7f6bb16b6b14d6, + 0xab5c852e8585d917, + 0x7381bdcebdbd3c67, + 0x34d25d695d5d8fba, + 0x5080104010109020, + 0x03f3f4f7f4f407f5, + 0xc016cb0bcbcbdd8b, + 0xc6ed3ef83e3ed37c, + 0x1128051405052d0a, + 0xe61f6781676778ce, + 0x5373e4b7e4e497d5, + 0xbb25279c2727024e, + 0x5832411941417382, + 0x9d2c8b168b8ba70b, + 0x0151a7a6a7a7f653, + 0x94cf7de97d7db2fa, + 0xfbdc956e95954937, + 0x9f8ed847d8d856ad, + 0x308bfbcbfbfb70eb, + 0x7123ee9feeeecdc1, + 0x91c77ced7c7cbbf8, + 0xe3176685666671cc, + 0x8ea6dd53dddd7ba7, + 0x4bb8175c1717af2e, + 0x460247014747458e, + 0xdc849e429e9e1a21, + 0xc51eca0fcacad489, + 0x99752db42d2d585a, + 0x7991bfc6bfbf2e63, + 0x1b38071c07073f0e, + 0x2301ad8eadadac47, + 0x2fea5a755a5ab0b4, + 0xb56c83368383ef1b, + 0xff8533cc3333b666, + 0xf23f639163635cc6, + 0x0a10020802021204, + 0x3839aa92aaaa9349, + 0xa8af71d97171dee2, + 0xcf0ec807c8c8c68d, + 0x7dc819641919d132, + 0x7072493949493b92, + 0x9a86d943d9d95faf, + 0x1dc3f2eff2f231f9, + 0x484be3abe3e3a8db, + 0x2ae25b715b5bb9b6, + 0x9234881a8888bc0d, + 0xc8a49a529a9a3e29, + 0xbe2d269826260b4c, + 0xfa8d32c83232bf64, + 0x4ae9b0fab0b0597d, + 0x6a1be983e9e9f2cf, + 0x33780f3c0f0f771e, + 0xa6e6d573d5d533b7, + 0xba74803a8080f41d, + 0x7c99bec2bebe2761, + 0xde26cd13cdcdeb87, + 0xe4bd34d034348968, + 0x757a483d48483290, + 0x24abffdbffff54e3, + 0x8ff77af57a7a8df4, + 0xeaf4907a9090643d, + 0x3ec25f615f5f9dbe, + 0xa01d208020203d40, + 0xd56768bd68680fd0, + 0x72d01a681a1aca34, + 0x2c19ae82aeaeb741, + 0x5ec9b4eab4b47d75, + 0x199a544d5454cea8, + 0xe5ec937693937f3b, + 0xaa0d228822222f44, + 0xe907648d646463c8, + 0x12dbf1e3f1f12aff, + 0xa2bf73d17373cce6, + 0x5a90124812128224, + 0x5d3a401d40407a80, + 0x2840082008084810, + 0xe856c32bc3c3959b, + 0x7b33ec97ececdfc5, + 0x9096db4bdbdb4dab, + 0x1f61a1bea1a1c05f, + 0x831c8d0e8d8d9107, + 0xc9f53df43d3dc87a, + 0xf1cc976697975b33, 0x0000000000000000, - 0x83f9cfcf1bcf36d4, - 0x566e2b2bac2b4587, - 0xece17676c57697b3, - 0x19e68282328264b0, - 0xb128d6d67fd6fea9, - 0x36c31b1b6c1bd877, - 0x7774b5b5eeb5c15b, - 0x43beafaf86af1129, - 0xd41d6a6ab56a77df, - 0xa0ea50505d50ba0d, - 0x8a5745450945124c, - 0xfb38f3f3ebf3cb18, - 0x60ad3030c0309df0, - 0xc3c4efef9bef2b74, - 0x7eda3f3ffc3fe5c3, - 0xaac755554955921c, - 0x59dba2a2b2a27910, - 0xc9e9eaea8fea0365, - 0xca6a656589650fec, - 0x6903babad2bab968, - 0x5e4a2f2fbc2f6593, - 0x9d8ec0c027c04ee7, - 0xa160dede5fdebe81, - 0x38fc1c1c701ce06c, - 0xe746fdfdd3fdbb2e, - 0x9a1f4d4d294d5264, - 0x397692927292e4e0, - 0xeafa7575c9758fbc, - 0x0c3606061806301e, - 0x09ae8a8a128a2498, - 0x794bb2b2f2b2f940, - 0xd185e6e6bfe66359, - 0x1c7e0e0e380e7036, - 0x3ee71f1f7c1ff863, - 0xc4556262956237f7, - 0xb53ad4d477d4eea3, - 0x4d81a8a89aa82932, - 0x315296966296c4f4, - 0xef62f9f9c3f99b3a, - 0x97a3c5c533c566f6, - 0x4a102525942535b1, - 0xb2ab59597959f220, - 0x15d084842a8454ae, - 0xe4c57272d572b7a7, - 0x72ec3939e439d5dd, - 0x98164c4c2d4c5a61, - 0xbc945e5e655eca3b, - 0xf09f7878fd78e785, - 0x70e53838e038ddd8, - 0x05988c8c0a8c1486, - 0xbf17d1d163d1c6b2, - 0x57e4a5a5aea5410b, - 0xd9a1e2e2afe2434d, - 0xc24e616199612ff8, - 0x7b42b3b3f6b3f145, - 0x42342121842115a5, - 0x25089c9c4a9c94d6, - 0x3cee1e1e781ef066, - 0x8661434311432252, - 0x93b1c7c73bc776fc, - 0xe54ffcfcd7fcb32b, - 0x0824040410042014, - 0xa2e351515951b208, - 0x2f2599995e99bcc7, - 0xda226d6da96d4fc4, - 0x1a650d0d340d6839, - 0xe979fafacffa8335, - 0xa369dfdf5bdfb684, - 0xfca97e7ee57ed79b, - 0x4819242490243db4, - 0x76fe3b3bec3bc5d7, - 0x4b9aabab96ab313d, - 0x81f0cece1fce3ed1, - 0x2299111144118855, - 0x03838f8f068f0c89, - 0x9c044e4e254e4a6b, - 0x7366b7b7e6b7d151, - 0xcbe0ebeb8beb0b60, - 0x78c13c3cf03cfdcc, - 0x1ffd81813e817cbf, - 0x354094946a94d4fe, - 0xf31cf7f7fbf7eb0c, - 0x6f18b9b9deb9a167, - 0x268b13134c13985f, - 0x58512c2cb02c7d9c, - 0xbb05d3d36bd3d6b8, - 0xd38ce7e7bbe76b5c, - 0xdc396e6ea56e57cb, - 0x95aac4c437c46ef3, - 0x061b03030c03180f, - 0xacdc565645568a13, - 0x885e44440d441a49, - 0xfea07f7fe17fdf9e, - 0x4f88a9a99ea92137, - 0x54672a2aa82a4d82, - 0x6b0abbbbd6bbb16d, - 0x9f87c1c123c146e2, - 0xa6f153535153a202, - 0xa572dcdc57dcae8b, - 0x16530b0b2c0b5827, - 0x27019d9d4e9d9cd3, - 0xd82b6c6cad6c47c1, - 0x62a43131c43195f5, - 0xe8f37474cd7487b9, - 0xf115f6f6fff6e309, - 0x8c4c464605460a43, - 0x45a5acac8aac0926, - 0x0fb589891e893c97, - 0x28b414145014a044, - 0xdfbae1e1a3e15b42, - 0x2ca616165816b04e, - 0x74f73a3ae83acdd2, - 0xd2066969b9696fd0, - 0x124109092409482d, - 0xe0d77070dd70a7ad, - 0x716fb6b6e2b6d954, - 0xbd1ed0d067d0ceb7, - 0xc7d6eded93ed3b7e, - 0x85e2cccc17cc2edb, - 0x8468424215422a57, - 0x2d2c98985a98b4c2, - 0x55eda4a4aaa4490e, - 0x50752828a0285d88, - 0xb8865c5c6d5cda31, - 0xed6bf8f8c7f8933f, - 0x11c28686228644a4, + 0xd436cf1bcfcff983, + 0x87452bac2b2b6e56, + 0xb39776c57676e1ec, + 0xb06482328282e619, + 0xa9fed67fd6d628b1, + 0x77d81b6c1b1bc336, + 0x5bc1b5eeb5b57477, + 0x2911af86afafbe43, + 0xdf776ab56a6a1dd4, + 0x0dba505d5050eaa0, + 0x4c1245094545578a, + 0x18cbf3ebf3f338fb, + 0xf09d30c03030ad60, + 0x742bef9befefc4c3, + 0xc3e53ffc3f3fda7e, + 0x1c9255495555c7aa, + 0x1079a2b2a2a2db59, + 0x6503ea8feaeae9c9, + 0xec0f658965656aca, + 0x68b9bad2baba0369, + 0x93652fbc2f2f4a5e, + 0xe74ec027c0c08e9d, + 0x81bede5fdede60a1, + 0x6ce01c701c1cfc38, + 0x2ebbfdd3fdfd46e7, + 0x64524d294d4d1f9a, + 0xe0e4927292927639, + 0xbc8f75c97575faea, + 0x1e3006180606360c, + 0x98248a128a8aae09, + 0x40f9b2f2b2b24b79, + 0x5963e6bfe6e685d1, + 0x36700e380e0e7e1c, + 0x63f81f7c1f1fe73e, + 0xf7376295626255c4, + 0xa3eed477d4d43ab5, + 0x3229a89aa8a8814d, + 0xf4c4966296965231, + 0x3a9bf9c3f9f962ef, + 0xf666c533c5c5a397, + 0xb13525942525104a, + 0x20f259795959abb2, + 0xae54842a8484d015, + 0xa7b772d57272c5e4, + 0xddd539e43939ec72, + 0x615a4c2d4c4c1698, + 0x3bca5e655e5e94bc, + 0x85e778fd78789ff0, + 0xd8dd38e03838e570, + 0x86148c0a8c8c9805, + 0xb2c6d163d1d117bf, + 0x0b41a5aea5a5e457, + 0x4d43e2afe2e2a1d9, + 0xf82f619961614ec2, + 0x45f1b3f6b3b3427b, + 0xa515218421213442, + 0xd6949c4a9c9c0825, + 0x66f01e781e1eee3c, + 0x5222431143436186, + 0xfc76c73bc7c7b193, + 0x2bb3fcd7fcfc4fe5, + 0x1420041004042408, + 0x08b251595151e3a2, + 0xc7bc995e9999252f, + 0xc44f6da96d6d22da, + 0x39680d340d0d651a, + 0x3583facffafa79e9, + 0x84b6df5bdfdf69a3, + 0x9bd77ee57e7ea9fc, + 0xb43d249024241948, + 0xd7c53bec3b3bfe76, + 0x3d31ab96abab9a4b, + 0xd13ece1fcecef081, + 0x5588114411119922, + 0x890c8f068f8f8303, + 0x6b4a4e254e4e049c, + 0x51d1b7e6b7b76673, + 0x600beb8bebebe0cb, + 0xccfd3cf03c3cc178, + 0xbf7c813e8181fd1f, + 0xfed4946a94944035, + 0x0cebf7fbf7f71cf3, + 0x67a1b9deb9b9186f, + 0x5f98134c13138b26, + 0x9c7d2cb02c2c5158, + 0xb8d6d36bd3d305bb, + 0x5c6be7bbe7e78cd3, + 0xcb576ea56e6e39dc, + 0xf36ec437c4c4aa95, + 0x0f18030c03031b06, + 0x138a56455656dcac, + 0x491a440d44445e88, + 0x9edf7fe17f7fa0fe, + 0x3721a99ea9a9884f, + 0x824d2aa82a2a6754, + 0x6db1bbd6bbbb0a6b, + 0xe246c123c1c1879f, + 0x02a253515353f1a6, + 0x8baedc57dcdc72a5, + 0x27580b2c0b0b5316, + 0xd39c9d4e9d9d0127, + 0xc1476cad6c6c2bd8, + 0xf59531c43131a462, + 0xb98774cd7474f3e8, + 0x09e3f6fff6f615f1, + 0x430a460546464c8c, + 0x2609ac8aacaca545, + 0x973c891e8989b50f, + 0x44a014501414b428, + 0x425be1a3e1e1badf, + 0x4eb016581616a62c, + 0xd2cd3ae83a3af774, + 0xd06f69b9696906d2, + 0x2d48092409094112, + 0xada770dd7070d7e0, + 0x54d9b6e2b6b66f71, + 0xb7ced067d0d01ebd, + 0x7e3bed93ededd6c7, + 0xdb2ecc17cccce285, + 0x572a421542426884, + 0xc2b4985a98982c2d, + 0x0e49a4aaa4a4ed55, + 0x885d28a028287550, + 0x31da5c6d5c5c86b8, + 0x3f93f8c7f8f86bed, + 0xa44486228686c211, ]; -pub static C3: [u64; 256] = [ - 0x7830d818186018c0, - 0xaf462623238c2305, - 0xf991b8c6c63fc67e, - 0x6fcdfbe8e887e813, - 0xa113cb878726874c, - 0x626d11b8b8dab8a9, - 0x0502090101040108, - 0x6e9e0d4f4f214f42, - 0xee6c9b3636d836ad, - 0x0451ffa6a6a2a659, - 0xbdb90cd2d26fd2de, - 0x06f70ef5f5f3f5fb, - 0x80f2967979f979ef, - 0xcede306f6fa16f5f, - 0xef3f6d91917e91fc, - 0x07a4f852525552aa, - 0xfdc04760609d6027, - 0x766535bcbccabc89, - 0xcd2b379b9b569bac, - 0x8c018a8e8e028e04, - 0x155bd2a3a3b6a371, - 0x3c186c0c0c300c60, - 0x8af6847b7bf17bff, - 0xe16a803535d435b5, - 0x693af51d1d741de8, - 0x47ddb3e0e0a7e053, - 0xacb321d7d77bd7f6, - 0xed999cc2c22fc25e, - 0x965c432e2eb82e6d, - 0x7a96294b4b314b62, - 0x21e15dfefedffea3, - 0x16aed55757415782, - 0x412abd15155415a8, - 0xb6eee87777c1779f, - 0xeb6e923737dc37a5, - 0x56d79ee5e5b3e57b, - 0xd923139f9f469f8c, - 0x17fd23f0f0e7f0d3, - 0x7f94204a4a354a6a, - 0x95a944dada4fda9e, - 0x25b0a258587d58fa, - 0xca8fcfc9c903c906, - 0x8d527c2929a42955, - 0x22145a0a0a280a50, - 0x4f7f50b1b1feb1e1, - 0x1a5dc9a0a0baa069, - 0xdad6146b6bb16b7f, - 0xab17d985852e855c, - 0x73673cbdbdcebd81, - 0x34ba8f5d5d695dd2, - 0x5020901010401080, - 0x03f507f4f4f7f4f3, - 0xc08bddcbcb0bcb16, - 0xc67cd33e3ef83eed, - 0x110a2d0505140528, - 0xe6ce78676781671f, - 0x53d597e4e4b7e473, - 0xbb4e0227279c2725, - 0x5882734141194132, - 0x9d0ba78b8b168b2c, - 0x0153f6a7a7a6a751, - 0x94fab27d7de97dcf, - 0xfb374995956e95dc, - 0x9fad56d8d847d88e, - 0x30eb70fbfbcbfb8b, - 0x71c1cdeeee9fee23, - 0x91f8bb7c7ced7cc7, - 0xe3cc716666856617, - 0x8ea77bdddd53dda6, - 0x4b2eaf17175c17b8, - 0x468e454747014702, - 0xdc211a9e9e429e84, - 0xc589d4caca0fca1e, - 0x995a582d2db42d75, - 0x79632ebfbfc6bf91, - 0x1b0e3f07071c0738, - 0x2347acadad8ead01, - 0x2fb4b05a5a755aea, - 0xb51bef838336836c, - 0xff66b63333cc3385, - 0xf2c65c636391633f, - 0x0a04120202080210, - 0x384993aaaa92aa39, - 0xa8e2de7171d971af, - 0xcf8dc6c8c807c80e, - 0x7d32d119196419c8, - 0x70923b4949394972, - 0x9aaf5fd9d943d986, - 0x1df931f2f2eff2c3, - 0x48dba8e3e3abe34b, - 0x2ab6b95b5b715be2, - 0x920dbc88881a8834, - 0xc8293e9a9a529aa4, - 0xbe4c0b262698262d, - 0xfa64bf3232c8328d, - 0x4a7d59b0b0fab0e9, - 0x6acff2e9e983e91b, - 0x331e770f0f3c0f78, - 0xa6b733d5d573d5e6, - 0xba1df480803a8074, - 0x7c6127bebec2be99, - 0xde87ebcdcd13cd26, - 0xe468893434d034bd, - 0x75903248483d487a, - 0x24e354ffffdbffab, - 0x8ff48d7a7af57af7, - 0xea3d6490907a90f4, - 0x3ebe9d5f5f615fc2, - 0xa0403d202080201d, - 0xd5d00f6868bd6867, - 0x7234ca1a1a681ad0, - 0x2c41b7aeae82ae19, - 0x5e757db4b4eab4c9, - 0x19a8ce54544d549a, - 0xe53b7f93937693ec, - 0xaa442f222288220d, - 0xe9c86364648d6407, - 0x12ff2af1f1e3f1db, - 0xa2e6cc7373d173bf, - 0x5a24821212481290, - 0x5d807a40401d403a, - 0x2810480808200840, - 0xe89b95c3c32bc356, - 0x7bc5dfecec97ec33, - 0x90ab4ddbdb4bdb96, - 0x1f5fc0a1a1bea161, - 0x8307918d8d0e8d1c, - 0xc97ac83d3df43df5, - 0xf1335b97976697cc, +pub const C3: [u64; 256] = [ + 0xc018601818d83078, + 0x05238c23232646af, + 0x7ec63fc6c6b891f9, + 0x13e887e8e8fbcd6f, + 0x4c87268787cb13a1, + 0xa9b8dab8b8116d62, + 0x0801040101090205, + 0x424f214f4f0d9e6e, + 0xad36d836369b6cee, + 0x59a6a2a6a6ff5104, + 0xded26fd2d20cb9bd, + 0xfbf5f3f5f50ef706, + 0xef79f9797996f280, + 0x5f6fa16f6f30dece, + 0xfc917e91916d3fef, + 0xaa52555252f8a407, + 0x27609d606047c0fd, + 0x89bccabcbc356576, + 0xac9b569b9b372bcd, + 0x048e028e8e8a018c, + 0x71a3b6a3a3d25b15, + 0x600c300c0c6c183c, + 0xff7bf17b7b84f68a, + 0xb535d43535806ae1, + 0xe81d741d1df53a69, + 0x53e0a7e0e0b3dd47, + 0xf6d77bd7d721b3ac, + 0x5ec22fc2c29c99ed, + 0x6d2eb82e2e435c96, + 0x624b314b4b29967a, + 0xa3fedffefe5de121, + 0x8257415757d5ae16, + 0xa815541515bd2a41, + 0x9f77c17777e8eeb6, + 0xa537dc3737926eeb, + 0x7be5b3e5e59ed756, + 0x8c9f469f9f1323d9, + 0xd3f0e7f0f023fd17, + 0x6a4a354a4a20947f, + 0x9eda4fdada44a995, + 0xfa587d5858a2b025, + 0x06c903c9c9cf8fca, + 0x5529a429297c528d, + 0x500a280a0a5a1422, + 0xe1b1feb1b1507f4f, + 0x69a0baa0a0c95d1a, + 0x7f6bb16b6b14d6da, + 0x5c852e8585d917ab, + 0x81bdcebdbd3c6773, + 0xd25d695d5d8fba34, + 0x8010401010902050, + 0xf3f4f7f4f407f503, + 0x16cb0bcbcbdd8bc0, + 0xed3ef83e3ed37cc6, + 0x28051405052d0a11, + 0x1f6781676778cee6, + 0x73e4b7e4e497d553, + 0x25279c2727024ebb, + 0x3241194141738258, + 0x2c8b168b8ba70b9d, + 0x51a7a6a7a7f65301, + 0xcf7de97d7db2fa94, + 0xdc956e95954937fb, + 0x8ed847d8d856ad9f, + 0x8bfbcbfbfb70eb30, + 0x23ee9feeeecdc171, + 0xc77ced7c7cbbf891, + 0x176685666671cce3, + 0xa6dd53dddd7ba78e, + 0xb8175c1717af2e4b, + 0x0247014747458e46, + 0x849e429e9e1a21dc, + 0x1eca0fcacad489c5, + 0x752db42d2d585a99, + 0x91bfc6bfbf2e6379, + 0x38071c07073f0e1b, + 0x01ad8eadadac4723, + 0xea5a755a5ab0b42f, + 0x6c83368383ef1bb5, + 0x8533cc3333b666ff, + 0x3f639163635cc6f2, + 0x100208020212040a, + 0x39aa92aaaa934938, + 0xaf71d97171dee2a8, + 0x0ec807c8c8c68dcf, + 0xc819641919d1327d, + 0x72493949493b9270, + 0x86d943d9d95faf9a, + 0xc3f2eff2f231f91d, + 0x4be3abe3e3a8db48, + 0xe25b715b5bb9b62a, + 0x34881a8888bc0d92, + 0xa49a529a9a3e29c8, + 0x2d269826260b4cbe, + 0x8d32c83232bf64fa, + 0xe9b0fab0b0597d4a, + 0x1be983e9e9f2cf6a, + 0x780f3c0f0f771e33, + 0xe6d573d5d533b7a6, + 0x74803a8080f41dba, + 0x99bec2bebe27617c, + 0x26cd13cdcdeb87de, + 0xbd34d034348968e4, + 0x7a483d4848329075, + 0xabffdbffff54e324, + 0xf77af57a7a8df48f, + 0xf4907a9090643dea, + 0xc25f615f5f9dbe3e, + 0x1d208020203d40a0, + 0x6768bd68680fd0d5, + 0xd01a681a1aca3472, + 0x19ae82aeaeb7412c, + 0xc9b4eab4b47d755e, + 0x9a544d5454cea819, + 0xec937693937f3be5, + 0x0d228822222f44aa, + 0x07648d646463c8e9, + 0xdbf1e3f1f12aff12, + 0xbf73d17373cce6a2, + 0x901248121282245a, + 0x3a401d40407a805d, + 0x4008200808481028, + 0x56c32bc3c3959be8, + 0x33ec97ececdfc57b, + 0x96db4bdbdb4dab90, + 0x61a1bea1a1c05f1f, + 0x1c8d0e8d8d910783, + 0xf53df43d3dc87ac9, + 0xcc976697975b33f1, 0x0000000000000000, - 0xd483f9cfcf1bcf36, - 0x87566e2b2bac2b45, - 0xb3ece17676c57697, - 0xb019e68282328264, - 0xa9b128d6d67fd6fe, - 0x7736c31b1b6c1bd8, - 0x5b7774b5b5eeb5c1, - 0x2943beafaf86af11, - 0xdfd41d6a6ab56a77, - 0x0da0ea50505d50ba, - 0x4c8a574545094512, - 0x18fb38f3f3ebf3cb, - 0xf060ad3030c0309d, - 0x74c3c4efef9bef2b, - 0xc37eda3f3ffc3fe5, - 0x1caac75555495592, - 0x1059dba2a2b2a279, - 0x65c9e9eaea8fea03, - 0xecca6a656589650f, - 0x686903babad2bab9, - 0x935e4a2f2fbc2f65, - 0xe79d8ec0c027c04e, - 0x81a160dede5fdebe, - 0x6c38fc1c1c701ce0, - 0x2ee746fdfdd3fdbb, - 0x649a1f4d4d294d52, - 0xe0397692927292e4, - 0xbceafa7575c9758f, - 0x1e0c360606180630, - 0x9809ae8a8a128a24, - 0x40794bb2b2f2b2f9, - 0x59d185e6e6bfe663, - 0x361c7e0e0e380e70, - 0x633ee71f1f7c1ff8, - 0xf7c4556262956237, - 0xa3b53ad4d477d4ee, - 0x324d81a8a89aa829, - 0xf4315296966296c4, - 0x3aef62f9f9c3f99b, - 0xf697a3c5c533c566, - 0xb14a102525942535, - 0x20b2ab59597959f2, - 0xae15d084842a8454, - 0xa7e4c57272d572b7, - 0xdd72ec3939e439d5, - 0x6198164c4c2d4c5a, - 0x3bbc945e5e655eca, - 0x85f09f7878fd78e7, - 0xd870e53838e038dd, - 0x8605988c8c0a8c14, - 0xb2bf17d1d163d1c6, - 0x0b57e4a5a5aea541, - 0x4dd9a1e2e2afe243, - 0xf8c24e616199612f, - 0x457b42b3b3f6b3f1, - 0xa542342121842115, - 0xd625089c9c4a9c94, - 0x663cee1e1e781ef0, - 0x5286614343114322, - 0xfc93b1c7c73bc776, - 0x2be54ffcfcd7fcb3, - 0x1408240404100420, - 0x08a2e351515951b2, - 0xc72f2599995e99bc, - 0xc4da226d6da96d4f, - 0x391a650d0d340d68, - 0x35e979fafacffa83, - 0x84a369dfdf5bdfb6, - 0x9bfca97e7ee57ed7, - 0xb44819242490243d, - 0xd776fe3b3bec3bc5, - 0x3d4b9aabab96ab31, - 0xd181f0cece1fce3e, - 0x5522991111441188, - 0x8903838f8f068f0c, - 0x6b9c044e4e254e4a, - 0x517366b7b7e6b7d1, - 0x60cbe0ebeb8beb0b, - 0xcc78c13c3cf03cfd, - 0xbf1ffd81813e817c, - 0xfe354094946a94d4, - 0x0cf31cf7f7fbf7eb, - 0x676f18b9b9deb9a1, - 0x5f268b13134c1398, - 0x9c58512c2cb02c7d, - 0xb8bb05d3d36bd3d6, - 0x5cd38ce7e7bbe76b, - 0xcbdc396e6ea56e57, - 0xf395aac4c437c46e, - 0x0f061b03030c0318, - 0x13acdc565645568a, - 0x49885e44440d441a, - 0x9efea07f7fe17fdf, - 0x374f88a9a99ea921, - 0x8254672a2aa82a4d, - 0x6d6b0abbbbd6bbb1, - 0xe29f87c1c123c146, - 0x02a6f153535153a2, - 0x8ba572dcdc57dcae, - 0x2716530b0b2c0b58, - 0xd327019d9d4e9d9c, - 0xc1d82b6c6cad6c47, - 0xf562a43131c43195, - 0xb9e8f37474cd7487, - 0x09f115f6f6fff6e3, - 0x438c4c464605460a, - 0x2645a5acac8aac09, - 0x970fb589891e893c, - 0x4428b414145014a0, - 0x42dfbae1e1a3e15b, - 0x4e2ca616165816b0, - 0xd274f73a3ae83acd, - 0xd0d2066969b9696f, - 0x2d12410909240948, - 0xade0d77070dd70a7, - 0x54716fb6b6e2b6d9, - 0xb7bd1ed0d067d0ce, - 0x7ec7d6eded93ed3b, - 0xdb85e2cccc17cc2e, - 0x578468424215422a, - 0xc22d2c98985a98b4, - 0x0e55eda4a4aaa449, - 0x8850752828a0285d, - 0x31b8865c5c6d5cda, - 0x3fed6bf8f8c7f893, - 0xa411c28686228644, + 0x36cf1bcfcff983d4, + 0x452bac2b2b6e5687, + 0x9776c57676e1ecb3, + 0x6482328282e619b0, + 0xfed67fd6d628b1a9, + 0xd81b6c1b1bc33677, + 0xc1b5eeb5b574775b, + 0x11af86afafbe4329, + 0x776ab56a6a1dd4df, + 0xba505d5050eaa00d, + 0x1245094545578a4c, + 0xcbf3ebf3f338fb18, + 0x9d30c03030ad60f0, + 0x2bef9befefc4c374, + 0xe53ffc3f3fda7ec3, + 0x9255495555c7aa1c, + 0x79a2b2a2a2db5910, + 0x03ea8feaeae9c965, + 0x0f658965656acaec, + 0xb9bad2baba036968, + 0x652fbc2f2f4a5e93, + 0x4ec027c0c08e9de7, + 0xbede5fdede60a181, + 0xe01c701c1cfc386c, + 0xbbfdd3fdfd46e72e, + 0x524d294d4d1f9a64, + 0xe4927292927639e0, + 0x8f75c97575faeabc, + 0x3006180606360c1e, + 0x248a128a8aae0998, + 0xf9b2f2b2b24b7940, + 0x63e6bfe6e685d159, + 0x700e380e0e7e1c36, + 0xf81f7c1f1fe73e63, + 0x376295626255c4f7, + 0xeed477d4d43ab5a3, + 0x29a89aa8a8814d32, + 0xc4966296965231f4, + 0x9bf9c3f9f962ef3a, + 0x66c533c5c5a397f6, + 0x3525942525104ab1, + 0xf259795959abb220, + 0x54842a8484d015ae, + 0xb772d57272c5e4a7, + 0xd539e43939ec72dd, + 0x5a4c2d4c4c169861, + 0xca5e655e5e94bc3b, + 0xe778fd78789ff085, + 0xdd38e03838e570d8, + 0x148c0a8c8c980586, + 0xc6d163d1d117bfb2, + 0x41a5aea5a5e4570b, + 0x43e2afe2e2a1d94d, + 0x2f619961614ec2f8, + 0xf1b3f6b3b3427b45, + 0x15218421213442a5, + 0x949c4a9c9c0825d6, + 0xf01e781e1eee3c66, + 0x2243114343618652, + 0x76c73bc7c7b193fc, + 0xb3fcd7fcfc4fe52b, + 0x2004100404240814, + 0xb251595151e3a208, + 0xbc995e9999252fc7, + 0x4f6da96d6d22dac4, + 0x680d340d0d651a39, + 0x83facffafa79e935, + 0xb6df5bdfdf69a384, + 0xd77ee57e7ea9fc9b, + 0x3d249024241948b4, + 0xc53bec3b3bfe76d7, + 0x31ab96abab9a4b3d, + 0x3ece1fcecef081d1, + 0x8811441111992255, + 0x0c8f068f8f830389, + 0x4a4e254e4e049c6b, + 0xd1b7e6b7b7667351, + 0x0beb8bebebe0cb60, + 0xfd3cf03c3cc178cc, + 0x7c813e8181fd1fbf, + 0xd4946a94944035fe, + 0xebf7fbf7f71cf30c, + 0xa1b9deb9b9186f67, + 0x98134c13138b265f, + 0x7d2cb02c2c51589c, + 0xd6d36bd3d305bbb8, + 0x6be7bbe7e78cd35c, + 0x576ea56e6e39dccb, + 0x6ec437c4c4aa95f3, + 0x18030c03031b060f, + 0x8a56455656dcac13, + 0x1a440d44445e8849, + 0xdf7fe17f7fa0fe9e, + 0x21a99ea9a9884f37, + 0x4d2aa82a2a675482, + 0xb1bbd6bbbb0a6b6d, + 0x46c123c1c1879fe2, + 0xa253515353f1a602, + 0xaedc57dcdc72a58b, + 0x580b2c0b0b531627, + 0x9c9d4e9d9d0127d3, + 0x476cad6c6c2bd8c1, + 0x9531c43131a462f5, + 0x8774cd7474f3e8b9, + 0xe3f6fff6f615f109, + 0x0a460546464c8c43, + 0x09ac8aacaca54526, + 0x3c891e8989b50f97, + 0xa014501414b42844, + 0x5be1a3e1e1badf42, + 0xb016581616a62c4e, + 0xcd3ae83a3af774d2, + 0x6f69b9696906d2d0, + 0x480924090941122d, + 0xa770dd7070d7e0ad, + 0xd9b6e2b6b66f7154, + 0xced067d0d01ebdb7, + 0x3bed93ededd6c77e, + 0x2ecc17cccce285db, + 0x2a42154242688457, + 0xb4985a98982c2dc2, + 0x49a4aaa4a4ed550e, + 0x5d28a02828755088, + 0xda5c6d5c5c86b831, + 0x93f8c7f8f86bed3f, + 0x4486228686c211a4, ]; -pub static C4: [u64; 256] = [ - 0xc07830d818186018, - 0x05af462623238c23, - 0x7ef991b8c6c63fc6, - 0x136fcdfbe8e887e8, - 0x4ca113cb87872687, - 0xa9626d11b8b8dab8, - 0x0805020901010401, - 0x426e9e0d4f4f214f, - 0xadee6c9b3636d836, - 0x590451ffa6a6a2a6, - 0xdebdb90cd2d26fd2, - 0xfb06f70ef5f5f3f5, - 0xef80f2967979f979, - 0x5fcede306f6fa16f, - 0xfcef3f6d91917e91, - 0xaa07a4f852525552, - 0x27fdc04760609d60, - 0x89766535bcbccabc, - 0xaccd2b379b9b569b, - 0x048c018a8e8e028e, - 0x71155bd2a3a3b6a3, - 0x603c186c0c0c300c, - 0xff8af6847b7bf17b, - 0xb5e16a803535d435, - 0xe8693af51d1d741d, - 0x5347ddb3e0e0a7e0, - 0xf6acb321d7d77bd7, - 0x5eed999cc2c22fc2, - 0x6d965c432e2eb82e, - 0x627a96294b4b314b, - 0xa321e15dfefedffe, - 0x8216aed557574157, - 0xa8412abd15155415, - 0x9fb6eee87777c177, - 0xa5eb6e923737dc37, - 0x7b56d79ee5e5b3e5, - 0x8cd923139f9f469f, - 0xd317fd23f0f0e7f0, - 0x6a7f94204a4a354a, - 0x9e95a944dada4fda, - 0xfa25b0a258587d58, - 0x06ca8fcfc9c903c9, - 0x558d527c2929a429, - 0x5022145a0a0a280a, - 0xe14f7f50b1b1feb1, - 0x691a5dc9a0a0baa0, - 0x7fdad6146b6bb16b, - 0x5cab17d985852e85, - 0x8173673cbdbdcebd, - 0xd234ba8f5d5d695d, - 0x8050209010104010, - 0xf303f507f4f4f7f4, - 0x16c08bddcbcb0bcb, - 0xedc67cd33e3ef83e, - 0x28110a2d05051405, - 0x1fe6ce7867678167, - 0x7353d597e4e4b7e4, - 0x25bb4e0227279c27, - 0x3258827341411941, - 0x2c9d0ba78b8b168b, - 0x510153f6a7a7a6a7, - 0xcf94fab27d7de97d, - 0xdcfb374995956e95, - 0x8e9fad56d8d847d8, - 0x8b30eb70fbfbcbfb, - 0x2371c1cdeeee9fee, - 0xc791f8bb7c7ced7c, - 0x17e3cc7166668566, - 0xa68ea77bdddd53dd, - 0xb84b2eaf17175c17, - 0x02468e4547470147, - 0x84dc211a9e9e429e, - 0x1ec589d4caca0fca, - 0x75995a582d2db42d, - 0x9179632ebfbfc6bf, - 0x381b0e3f07071c07, - 0x012347acadad8ead, - 0xea2fb4b05a5a755a, - 0x6cb51bef83833683, - 0x85ff66b63333cc33, - 0x3ff2c65c63639163, - 0x100a041202020802, - 0x39384993aaaa92aa, - 0xafa8e2de7171d971, - 0x0ecf8dc6c8c807c8, - 0xc87d32d119196419, - 0x7270923b49493949, - 0x869aaf5fd9d943d9, - 0xc31df931f2f2eff2, - 0x4b48dba8e3e3abe3, - 0xe22ab6b95b5b715b, - 0x34920dbc88881a88, - 0xa4c8293e9a9a529a, - 0x2dbe4c0b26269826, - 0x8dfa64bf3232c832, - 0xe94a7d59b0b0fab0, - 0x1b6acff2e9e983e9, - 0x78331e770f0f3c0f, - 0xe6a6b733d5d573d5, - 0x74ba1df480803a80, - 0x997c6127bebec2be, - 0x26de87ebcdcd13cd, - 0xbde468893434d034, - 0x7a75903248483d48, - 0xab24e354ffffdbff, - 0xf78ff48d7a7af57a, - 0xf4ea3d6490907a90, - 0xc23ebe9d5f5f615f, - 0x1da0403d20208020, - 0x67d5d00f6868bd68, - 0xd07234ca1a1a681a, - 0x192c41b7aeae82ae, - 0xc95e757db4b4eab4, - 0x9a19a8ce54544d54, - 0xece53b7f93937693, - 0x0daa442f22228822, - 0x07e9c86364648d64, - 0xdb12ff2af1f1e3f1, - 0xbfa2e6cc7373d173, - 0x905a248212124812, - 0x3a5d807a40401d40, - 0x4028104808082008, - 0x56e89b95c3c32bc3, - 0x337bc5dfecec97ec, - 0x9690ab4ddbdb4bdb, - 0x611f5fc0a1a1bea1, - 0x1c8307918d8d0e8d, - 0xf5c97ac83d3df43d, - 0xccf1335b97976697, +pub const C4: [u64; 256] = [ + 0x18601818d83078c0, + 0x238c23232646af05, + 0xc63fc6c6b891f97e, + 0xe887e8e8fbcd6f13, + 0x87268787cb13a14c, + 0xb8dab8b8116d62a9, + 0x0104010109020508, + 0x4f214f4f0d9e6e42, + 0x36d836369b6ceead, + 0xa6a2a6a6ff510459, + 0xd26fd2d20cb9bdde, + 0xf5f3f5f50ef706fb, + 0x79f9797996f280ef, + 0x6fa16f6f30dece5f, + 0x917e91916d3feffc, + 0x52555252f8a407aa, + 0x609d606047c0fd27, + 0xbccabcbc35657689, + 0x9b569b9b372bcdac, + 0x8e028e8e8a018c04, + 0xa3b6a3a3d25b1571, + 0x0c300c0c6c183c60, + 0x7bf17b7b84f68aff, + 0x35d43535806ae1b5, + 0x1d741d1df53a69e8, + 0xe0a7e0e0b3dd4753, + 0xd77bd7d721b3acf6, + 0xc22fc2c29c99ed5e, + 0x2eb82e2e435c966d, + 0x4b314b4b29967a62, + 0xfedffefe5de121a3, + 0x57415757d5ae1682, + 0x15541515bd2a41a8, + 0x77c17777e8eeb69f, + 0x37dc3737926eeba5, + 0xe5b3e5e59ed7567b, + 0x9f469f9f1323d98c, + 0xf0e7f0f023fd17d3, + 0x4a354a4a20947f6a, + 0xda4fdada44a9959e, + 0x587d5858a2b025fa, + 0xc903c9c9cf8fca06, + 0x29a429297c528d55, + 0x0a280a0a5a142250, + 0xb1feb1b1507f4fe1, + 0xa0baa0a0c95d1a69, + 0x6bb16b6b14d6da7f, + 0x852e8585d917ab5c, + 0xbdcebdbd3c677381, + 0x5d695d5d8fba34d2, + 0x1040101090205080, + 0xf4f7f4f407f503f3, + 0xcb0bcbcbdd8bc016, + 0x3ef83e3ed37cc6ed, + 0x051405052d0a1128, + 0x6781676778cee61f, + 0xe4b7e4e497d55373, + 0x279c2727024ebb25, + 0x4119414173825832, + 0x8b168b8ba70b9d2c, + 0xa7a6a7a7f6530151, + 0x7de97d7db2fa94cf, + 0x956e95954937fbdc, + 0xd847d8d856ad9f8e, + 0xfbcbfbfb70eb308b, + 0xee9feeeecdc17123, + 0x7ced7c7cbbf891c7, + 0x6685666671cce317, + 0xdd53dddd7ba78ea6, + 0x175c1717af2e4bb8, + 0x47014747458e4602, + 0x9e429e9e1a21dc84, + 0xca0fcacad489c51e, + 0x2db42d2d585a9975, + 0xbfc6bfbf2e637991, + 0x071c07073f0e1b38, + 0xad8eadadac472301, + 0x5a755a5ab0b42fea, + 0x83368383ef1bb56c, + 0x33cc3333b666ff85, + 0x639163635cc6f23f, + 0x0208020212040a10, + 0xaa92aaaa93493839, + 0x71d97171dee2a8af, + 0xc807c8c8c68dcf0e, + 0x19641919d1327dc8, + 0x493949493b927072, + 0xd943d9d95faf9a86, + 0xf2eff2f231f91dc3, + 0xe3abe3e3a8db484b, + 0x5b715b5bb9b62ae2, + 0x881a8888bc0d9234, + 0x9a529a9a3e29c8a4, + 0x269826260b4cbe2d, + 0x32c83232bf64fa8d, + 0xb0fab0b0597d4ae9, + 0xe983e9e9f2cf6a1b, + 0x0f3c0f0f771e3378, + 0xd573d5d533b7a6e6, + 0x803a8080f41dba74, + 0xbec2bebe27617c99, + 0xcd13cdcdeb87de26, + 0x34d034348968e4bd, + 0x483d48483290757a, + 0xffdbffff54e324ab, + 0x7af57a7a8df48ff7, + 0x907a9090643deaf4, + 0x5f615f5f9dbe3ec2, + 0x208020203d40a01d, + 0x68bd68680fd0d567, + 0x1a681a1aca3472d0, + 0xae82aeaeb7412c19, + 0xb4eab4b47d755ec9, + 0x544d5454cea8199a, + 0x937693937f3be5ec, + 0x228822222f44aa0d, + 0x648d646463c8e907, + 0xf1e3f1f12aff12db, + 0x73d17373cce6a2bf, + 0x1248121282245a90, + 0x401d40407a805d3a, + 0x0820080848102840, + 0xc32bc3c3959be856, + 0xec97ececdfc57b33, + 0xdb4bdbdb4dab9096, + 0xa1bea1a1c05f1f61, + 0x8d0e8d8d9107831c, + 0x3df43d3dc87ac9f5, + 0x976697975b33f1cc, 0x0000000000000000, - 0x36d483f9cfcf1bcf, - 0x4587566e2b2bac2b, - 0x97b3ece17676c576, - 0x64b019e682823282, - 0xfea9b128d6d67fd6, - 0xd87736c31b1b6c1b, - 0xc15b7774b5b5eeb5, - 0x112943beafaf86af, - 0x77dfd41d6a6ab56a, - 0xba0da0ea50505d50, - 0x124c8a5745450945, - 0xcb18fb38f3f3ebf3, - 0x9df060ad3030c030, - 0x2b74c3c4efef9bef, - 0xe5c37eda3f3ffc3f, - 0x921caac755554955, - 0x791059dba2a2b2a2, - 0x0365c9e9eaea8fea, - 0x0fecca6a65658965, - 0xb9686903babad2ba, - 0x65935e4a2f2fbc2f, - 0x4ee79d8ec0c027c0, - 0xbe81a160dede5fde, - 0xe06c38fc1c1c701c, - 0xbb2ee746fdfdd3fd, - 0x52649a1f4d4d294d, - 0xe4e0397692927292, - 0x8fbceafa7575c975, - 0x301e0c3606061806, - 0x249809ae8a8a128a, - 0xf940794bb2b2f2b2, - 0x6359d185e6e6bfe6, - 0x70361c7e0e0e380e, - 0xf8633ee71f1f7c1f, - 0x37f7c45562629562, - 0xeea3b53ad4d477d4, - 0x29324d81a8a89aa8, - 0xc4f4315296966296, - 0x9b3aef62f9f9c3f9, - 0x66f697a3c5c533c5, - 0x35b14a1025259425, - 0xf220b2ab59597959, - 0x54ae15d084842a84, - 0xb7a7e4c57272d572, - 0xd5dd72ec3939e439, - 0x5a6198164c4c2d4c, - 0xca3bbc945e5e655e, - 0xe785f09f7878fd78, - 0xddd870e53838e038, - 0x148605988c8c0a8c, - 0xc6b2bf17d1d163d1, - 0x410b57e4a5a5aea5, - 0x434dd9a1e2e2afe2, - 0x2ff8c24e61619961, - 0xf1457b42b3b3f6b3, - 0x15a5423421218421, - 0x94d625089c9c4a9c, - 0xf0663cee1e1e781e, - 0x2252866143431143, - 0x76fc93b1c7c73bc7, - 0xb32be54ffcfcd7fc, - 0x2014082404041004, - 0xb208a2e351515951, - 0xbcc72f2599995e99, - 0x4fc4da226d6da96d, - 0x68391a650d0d340d, - 0x8335e979fafacffa, - 0xb684a369dfdf5bdf, - 0xd79bfca97e7ee57e, - 0x3db4481924249024, - 0xc5d776fe3b3bec3b, - 0x313d4b9aabab96ab, - 0x3ed181f0cece1fce, - 0x8855229911114411, - 0x0c8903838f8f068f, - 0x4a6b9c044e4e254e, - 0xd1517366b7b7e6b7, - 0x0b60cbe0ebeb8beb, - 0xfdcc78c13c3cf03c, - 0x7cbf1ffd81813e81, - 0xd4fe354094946a94, - 0xeb0cf31cf7f7fbf7, - 0xa1676f18b9b9deb9, - 0x985f268b13134c13, - 0x7d9c58512c2cb02c, - 0xd6b8bb05d3d36bd3, - 0x6b5cd38ce7e7bbe7, - 0x57cbdc396e6ea56e, - 0x6ef395aac4c437c4, - 0x180f061b03030c03, - 0x8a13acdc56564556, - 0x1a49885e44440d44, - 0xdf9efea07f7fe17f, - 0x21374f88a9a99ea9, - 0x4d8254672a2aa82a, - 0xb16d6b0abbbbd6bb, - 0x46e29f87c1c123c1, - 0xa202a6f153535153, - 0xae8ba572dcdc57dc, - 0x582716530b0b2c0b, - 0x9cd327019d9d4e9d, - 0x47c1d82b6c6cad6c, - 0x95f562a43131c431, - 0x87b9e8f37474cd74, - 0xe309f115f6f6fff6, - 0x0a438c4c46460546, - 0x092645a5acac8aac, - 0x3c970fb589891e89, - 0xa04428b414145014, - 0x5b42dfbae1e1a3e1, - 0xb04e2ca616165816, - 0xcdd274f73a3ae83a, - 0x6fd0d2066969b969, - 0x482d124109092409, - 0xa7ade0d77070dd70, - 0xd954716fb6b6e2b6, - 0xceb7bd1ed0d067d0, - 0x3b7ec7d6eded93ed, - 0x2edb85e2cccc17cc, - 0x2a57846842421542, - 0xb4c22d2c98985a98, - 0x490e55eda4a4aaa4, - 0x5d8850752828a028, - 0xda31b8865c5c6d5c, - 0x933fed6bf8f8c7f8, - 0x44a411c286862286, + 0xcf1bcfcff983d436, + 0x2bac2b2b6e568745, + 0x76c57676e1ecb397, + 0x82328282e619b064, + 0xd67fd6d628b1a9fe, + 0x1b6c1b1bc33677d8, + 0xb5eeb5b574775bc1, + 0xaf86afafbe432911, + 0x6ab56a6a1dd4df77, + 0x505d5050eaa00dba, + 0x45094545578a4c12, + 0xf3ebf3f338fb18cb, + 0x30c03030ad60f09d, + 0xef9befefc4c3742b, + 0x3ffc3f3fda7ec3e5, + 0x55495555c7aa1c92, + 0xa2b2a2a2db591079, + 0xea8feaeae9c96503, + 0x658965656acaec0f, + 0xbad2baba036968b9, + 0x2fbc2f2f4a5e9365, + 0xc027c0c08e9de74e, + 0xde5fdede60a181be, + 0x1c701c1cfc386ce0, + 0xfdd3fdfd46e72ebb, + 0x4d294d4d1f9a6452, + 0x927292927639e0e4, + 0x75c97575faeabc8f, + 0x06180606360c1e30, + 0x8a128a8aae099824, + 0xb2f2b2b24b7940f9, + 0xe6bfe6e685d15963, + 0x0e380e0e7e1c3670, + 0x1f7c1f1fe73e63f8, + 0x6295626255c4f737, + 0xd477d4d43ab5a3ee, + 0xa89aa8a8814d3229, + 0x966296965231f4c4, + 0xf9c3f9f962ef3a9b, + 0xc533c5c5a397f666, + 0x25942525104ab135, + 0x59795959abb220f2, + 0x842a8484d015ae54, + 0x72d57272c5e4a7b7, + 0x39e43939ec72ddd5, + 0x4c2d4c4c1698615a, + 0x5e655e5e94bc3bca, + 0x78fd78789ff085e7, + 0x38e03838e570d8dd, + 0x8c0a8c8c98058614, + 0xd163d1d117bfb2c6, + 0xa5aea5a5e4570b41, + 0xe2afe2e2a1d94d43, + 0x619961614ec2f82f, + 0xb3f6b3b3427b45f1, + 0x218421213442a515, + 0x9c4a9c9c0825d694, + 0x1e781e1eee3c66f0, + 0x4311434361865222, + 0xc73bc7c7b193fc76, + 0xfcd7fcfc4fe52bb3, + 0x0410040424081420, + 0x51595151e3a208b2, + 0x995e9999252fc7bc, + 0x6da96d6d22dac44f, + 0x0d340d0d651a3968, + 0xfacffafa79e93583, + 0xdf5bdfdf69a384b6, + 0x7ee57e7ea9fc9bd7, + 0x249024241948b43d, + 0x3bec3b3bfe76d7c5, + 0xab96abab9a4b3d31, + 0xce1fcecef081d13e, + 0x1144111199225588, + 0x8f068f8f8303890c, + 0x4e254e4e049c6b4a, + 0xb7e6b7b7667351d1, + 0xeb8bebebe0cb600b, + 0x3cf03c3cc178ccfd, + 0x813e8181fd1fbf7c, + 0x946a94944035fed4, + 0xf7fbf7f71cf30ceb, + 0xb9deb9b9186f67a1, + 0x134c13138b265f98, + 0x2cb02c2c51589c7d, + 0xd36bd3d305bbb8d6, + 0xe7bbe7e78cd35c6b, + 0x6ea56e6e39dccb57, + 0xc437c4c4aa95f36e, + 0x030c03031b060f18, + 0x56455656dcac138a, + 0x440d44445e88491a, + 0x7fe17f7fa0fe9edf, + 0xa99ea9a9884f3721, + 0x2aa82a2a6754824d, + 0xbbd6bbbb0a6b6db1, + 0xc123c1c1879fe246, + 0x53515353f1a602a2, + 0xdc57dcdc72a58bae, + 0x0b2c0b0b53162758, + 0x9d4e9d9d0127d39c, + 0x6cad6c6c2bd8c147, + 0x31c43131a462f595, + 0x74cd7474f3e8b987, + 0xf6fff6f615f109e3, + 0x460546464c8c430a, + 0xac8aacaca5452609, + 0x891e8989b50f973c, + 0x14501414b42844a0, + 0xe1a3e1e1badf425b, + 0x16581616a62c4eb0, + 0x3ae83a3af774d2cd, + 0x69b9696906d2d06f, + 0x0924090941122d48, + 0x70dd7070d7e0ada7, + 0xb6e2b6b66f7154d9, + 0xd067d0d01ebdb7ce, + 0xed93ededd6c77e3b, + 0xcc17cccce285db2e, + 0x421542426884572a, + 0x985a98982c2dc2b4, + 0xa4aaa4a4ed550e49, + 0x28a028287550885d, + 0x5c6d5c5c86b831da, + 0xf8c7f8f86bed3f93, + 0x86228686c211a444, ]; -pub static C5: [u64; 256] = [ - 0x18c07830d8181860, - 0x2305af462623238c, - 0xc67ef991b8c6c63f, - 0xe8136fcdfbe8e887, - 0x874ca113cb878726, - 0xb8a9626d11b8b8da, - 0x0108050209010104, - 0x4f426e9e0d4f4f21, - 0x36adee6c9b3636d8, - 0xa6590451ffa6a6a2, - 0xd2debdb90cd2d26f, - 0xf5fb06f70ef5f5f3, - 0x79ef80f2967979f9, - 0x6f5fcede306f6fa1, - 0x91fcef3f6d91917e, - 0x52aa07a4f8525255, - 0x6027fdc04760609d, - 0xbc89766535bcbcca, - 0x9baccd2b379b9b56, - 0x8e048c018a8e8e02, - 0xa371155bd2a3a3b6, - 0x0c603c186c0c0c30, - 0x7bff8af6847b7bf1, - 0x35b5e16a803535d4, - 0x1de8693af51d1d74, - 0xe05347ddb3e0e0a7, - 0xd7f6acb321d7d77b, - 0xc25eed999cc2c22f, - 0x2e6d965c432e2eb8, - 0x4b627a96294b4b31, - 0xfea321e15dfefedf, - 0x578216aed5575741, - 0x15a8412abd151554, - 0x779fb6eee87777c1, - 0x37a5eb6e923737dc, - 0xe57b56d79ee5e5b3, - 0x9f8cd923139f9f46, - 0xf0d317fd23f0f0e7, - 0x4a6a7f94204a4a35, - 0xda9e95a944dada4f, - 0x58fa25b0a258587d, - 0xc906ca8fcfc9c903, - 0x29558d527c2929a4, - 0x0a5022145a0a0a28, - 0xb1e14f7f50b1b1fe, - 0xa0691a5dc9a0a0ba, - 0x6b7fdad6146b6bb1, - 0x855cab17d985852e, - 0xbd8173673cbdbdce, - 0x5dd234ba8f5d5d69, - 0x1080502090101040, - 0xf4f303f507f4f4f7, - 0xcb16c08bddcbcb0b, - 0x3eedc67cd33e3ef8, - 0x0528110a2d050514, - 0x671fe6ce78676781, - 0xe47353d597e4e4b7, - 0x2725bb4e0227279c, - 0x4132588273414119, - 0x8b2c9d0ba78b8b16, - 0xa7510153f6a7a7a6, - 0x7dcf94fab27d7de9, - 0x95dcfb374995956e, - 0xd88e9fad56d8d847, - 0xfb8b30eb70fbfbcb, - 0xee2371c1cdeeee9f, - 0x7cc791f8bb7c7ced, - 0x6617e3cc71666685, - 0xdda68ea77bdddd53, - 0x17b84b2eaf17175c, - 0x4702468e45474701, - 0x9e84dc211a9e9e42, - 0xca1ec589d4caca0f, - 0x2d75995a582d2db4, - 0xbf9179632ebfbfc6, - 0x07381b0e3f07071c, - 0xad012347acadad8e, - 0x5aea2fb4b05a5a75, - 0x836cb51bef838336, - 0x3385ff66b63333cc, - 0x633ff2c65c636391, - 0x02100a0412020208, - 0xaa39384993aaaa92, - 0x71afa8e2de7171d9, - 0xc80ecf8dc6c8c807, - 0x19c87d32d1191964, - 0x497270923b494939, - 0xd9869aaf5fd9d943, - 0xf2c31df931f2f2ef, - 0xe34b48dba8e3e3ab, - 0x5be22ab6b95b5b71, - 0x8834920dbc88881a, - 0x9aa4c8293e9a9a52, - 0x262dbe4c0b262698, - 0x328dfa64bf3232c8, - 0xb0e94a7d59b0b0fa, - 0xe91b6acff2e9e983, - 0x0f78331e770f0f3c, - 0xd5e6a6b733d5d573, - 0x8074ba1df480803a, - 0xbe997c6127bebec2, - 0xcd26de87ebcdcd13, - 0x34bde468893434d0, - 0x487a75903248483d, - 0xffab24e354ffffdb, - 0x7af78ff48d7a7af5, - 0x90f4ea3d6490907a, - 0x5fc23ebe9d5f5f61, - 0x201da0403d202080, - 0x6867d5d00f6868bd, - 0x1ad07234ca1a1a68, - 0xae192c41b7aeae82, - 0xb4c95e757db4b4ea, - 0x549a19a8ce54544d, - 0x93ece53b7f939376, - 0x220daa442f222288, - 0x6407e9c86364648d, - 0xf1db12ff2af1f1e3, - 0x73bfa2e6cc7373d1, - 0x12905a2482121248, - 0x403a5d807a40401d, - 0x0840281048080820, - 0xc356e89b95c3c32b, - 0xec337bc5dfecec97, - 0xdb9690ab4ddbdb4b, - 0xa1611f5fc0a1a1be, - 0x8d1c8307918d8d0e, - 0x3df5c97ac83d3df4, - 0x97ccf1335b979766, +pub const C5: [u64; 256] = [ + 0x601818d83078c018, + 0x8c23232646af0523, + 0x3fc6c6b891f97ec6, + 0x87e8e8fbcd6f13e8, + 0x268787cb13a14c87, + 0xdab8b8116d62a9b8, + 0x0401010902050801, + 0x214f4f0d9e6e424f, + 0xd836369b6ceead36, + 0xa2a6a6ff510459a6, + 0x6fd2d20cb9bdded2, + 0xf3f5f50ef706fbf5, + 0xf9797996f280ef79, + 0xa16f6f30dece5f6f, + 0x7e91916d3feffc91, + 0x555252f8a407aa52, + 0x9d606047c0fd2760, + 0xcabcbc35657689bc, + 0x569b9b372bcdac9b, + 0x028e8e8a018c048e, + 0xb6a3a3d25b1571a3, + 0x300c0c6c183c600c, + 0xf17b7b84f68aff7b, + 0xd43535806ae1b535, + 0x741d1df53a69e81d, + 0xa7e0e0b3dd4753e0, + 0x7bd7d721b3acf6d7, + 0x2fc2c29c99ed5ec2, + 0xb82e2e435c966d2e, + 0x314b4b29967a624b, + 0xdffefe5de121a3fe, + 0x415757d5ae168257, + 0x541515bd2a41a815, + 0xc17777e8eeb69f77, + 0xdc3737926eeba537, + 0xb3e5e59ed7567be5, + 0x469f9f1323d98c9f, + 0xe7f0f023fd17d3f0, + 0x354a4a20947f6a4a, + 0x4fdada44a9959eda, + 0x7d5858a2b025fa58, + 0x03c9c9cf8fca06c9, + 0xa429297c528d5529, + 0x280a0a5a1422500a, + 0xfeb1b1507f4fe1b1, + 0xbaa0a0c95d1a69a0, + 0xb16b6b14d6da7f6b, + 0x2e8585d917ab5c85, + 0xcebdbd3c677381bd, + 0x695d5d8fba34d25d, + 0x4010109020508010, + 0xf7f4f407f503f3f4, + 0x0bcbcbdd8bc016cb, + 0xf83e3ed37cc6ed3e, + 0x1405052d0a112805, + 0x81676778cee61f67, + 0xb7e4e497d55373e4, + 0x9c2727024ebb2527, + 0x1941417382583241, + 0x168b8ba70b9d2c8b, + 0xa6a7a7f6530151a7, + 0xe97d7db2fa94cf7d, + 0x6e95954937fbdc95, + 0x47d8d856ad9f8ed8, + 0xcbfbfb70eb308bfb, + 0x9feeeecdc17123ee, + 0xed7c7cbbf891c77c, + 0x85666671cce31766, + 0x53dddd7ba78ea6dd, + 0x5c1717af2e4bb817, + 0x014747458e460247, + 0x429e9e1a21dc849e, + 0x0fcacad489c51eca, + 0xb42d2d585a99752d, + 0xc6bfbf2e637991bf, + 0x1c07073f0e1b3807, + 0x8eadadac472301ad, + 0x755a5ab0b42fea5a, + 0x368383ef1bb56c83, + 0xcc3333b666ff8533, + 0x9163635cc6f23f63, + 0x08020212040a1002, + 0x92aaaa93493839aa, + 0xd97171dee2a8af71, + 0x07c8c8c68dcf0ec8, + 0x641919d1327dc819, + 0x3949493b92707249, + 0x43d9d95faf9a86d9, + 0xeff2f231f91dc3f2, + 0xabe3e3a8db484be3, + 0x715b5bb9b62ae25b, + 0x1a8888bc0d923488, + 0x529a9a3e29c8a49a, + 0x9826260b4cbe2d26, + 0xc83232bf64fa8d32, + 0xfab0b0597d4ae9b0, + 0x83e9e9f2cf6a1be9, + 0x3c0f0f771e33780f, + 0x73d5d533b7a6e6d5, + 0x3a8080f41dba7480, + 0xc2bebe27617c99be, + 0x13cdcdeb87de26cd, + 0xd034348968e4bd34, + 0x3d48483290757a48, + 0xdbffff54e324abff, + 0xf57a7a8df48ff77a, + 0x7a9090643deaf490, + 0x615f5f9dbe3ec25f, + 0x8020203d40a01d20, + 0xbd68680fd0d56768, + 0x681a1aca3472d01a, + 0x82aeaeb7412c19ae, + 0xeab4b47d755ec9b4, + 0x4d5454cea8199a54, + 0x7693937f3be5ec93, + 0x8822222f44aa0d22, + 0x8d646463c8e90764, + 0xe3f1f12aff12dbf1, + 0xd17373cce6a2bf73, + 0x48121282245a9012, + 0x1d40407a805d3a40, + 0x2008084810284008, + 0x2bc3c3959be856c3, + 0x97ececdfc57b33ec, + 0x4bdbdb4dab9096db, + 0xbea1a1c05f1f61a1, + 0x0e8d8d9107831c8d, + 0xf43d3dc87ac9f53d, + 0x6697975b33f1cc97, 0x0000000000000000, - 0xcf36d483f9cfcf1b, - 0x2b4587566e2b2bac, - 0x7697b3ece17676c5, - 0x8264b019e6828232, - 0xd6fea9b128d6d67f, - 0x1bd87736c31b1b6c, - 0xb5c15b7774b5b5ee, - 0xaf112943beafaf86, - 0x6a77dfd41d6a6ab5, - 0x50ba0da0ea50505d, - 0x45124c8a57454509, - 0xf3cb18fb38f3f3eb, - 0x309df060ad3030c0, - 0xef2b74c3c4efef9b, - 0x3fe5c37eda3f3ffc, - 0x55921caac7555549, - 0xa2791059dba2a2b2, - 0xea0365c9e9eaea8f, - 0x650fecca6a656589, - 0xbab9686903babad2, - 0x2f65935e4a2f2fbc, - 0xc04ee79d8ec0c027, - 0xdebe81a160dede5f, - 0x1ce06c38fc1c1c70, - 0xfdbb2ee746fdfdd3, - 0x4d52649a1f4d4d29, - 0x92e4e03976929272, - 0x758fbceafa7575c9, - 0x06301e0c36060618, - 0x8a249809ae8a8a12, - 0xb2f940794bb2b2f2, - 0xe66359d185e6e6bf, - 0x0e70361c7e0e0e38, - 0x1ff8633ee71f1f7c, - 0x6237f7c455626295, - 0xd4eea3b53ad4d477, - 0xa829324d81a8a89a, - 0x96c4f43152969662, - 0xf99b3aef62f9f9c3, - 0xc566f697a3c5c533, - 0x2535b14a10252594, - 0x59f220b2ab595979, - 0x8454ae15d084842a, - 0x72b7a7e4c57272d5, - 0x39d5dd72ec3939e4, - 0x4c5a6198164c4c2d, - 0x5eca3bbc945e5e65, - 0x78e785f09f7878fd, - 0x38ddd870e53838e0, - 0x8c148605988c8c0a, - 0xd1c6b2bf17d1d163, - 0xa5410b57e4a5a5ae, - 0xe2434dd9a1e2e2af, - 0x612ff8c24e616199, - 0xb3f1457b42b3b3f6, - 0x2115a54234212184, - 0x9c94d625089c9c4a, - 0x1ef0663cee1e1e78, - 0x4322528661434311, - 0xc776fc93b1c7c73b, - 0xfcb32be54ffcfcd7, - 0x0420140824040410, - 0x51b208a2e3515159, - 0x99bcc72f2599995e, - 0x6d4fc4da226d6da9, - 0x0d68391a650d0d34, - 0xfa8335e979fafacf, - 0xdfb684a369dfdf5b, - 0x7ed79bfca97e7ee5, - 0x243db44819242490, - 0x3bc5d776fe3b3bec, - 0xab313d4b9aabab96, - 0xce3ed181f0cece1f, - 0x1188552299111144, - 0x8f0c8903838f8f06, - 0x4e4a6b9c044e4e25, - 0xb7d1517366b7b7e6, - 0xeb0b60cbe0ebeb8b, - 0x3cfdcc78c13c3cf0, - 0x817cbf1ffd81813e, - 0x94d4fe354094946a, - 0xf7eb0cf31cf7f7fb, - 0xb9a1676f18b9b9de, - 0x13985f268b13134c, - 0x2c7d9c58512c2cb0, - 0xd3d6b8bb05d3d36b, - 0xe76b5cd38ce7e7bb, - 0x6e57cbdc396e6ea5, - 0xc46ef395aac4c437, - 0x03180f061b03030c, - 0x568a13acdc565645, - 0x441a49885e44440d, - 0x7fdf9efea07f7fe1, - 0xa921374f88a9a99e, - 0x2a4d8254672a2aa8, - 0xbbb16d6b0abbbbd6, - 0xc146e29f87c1c123, - 0x53a202a6f1535351, - 0xdcae8ba572dcdc57, - 0x0b582716530b0b2c, - 0x9d9cd327019d9d4e, - 0x6c47c1d82b6c6cad, - 0x3195f562a43131c4, - 0x7487b9e8f37474cd, - 0xf6e309f115f6f6ff, - 0x460a438c4c464605, - 0xac092645a5acac8a, - 0x893c970fb589891e, - 0x14a04428b4141450, - 0xe15b42dfbae1e1a3, - 0x16b04e2ca6161658, - 0x3acdd274f73a3ae8, - 0x696fd0d2066969b9, - 0x09482d1241090924, - 0x70a7ade0d77070dd, - 0xb6d954716fb6b6e2, - 0xd0ceb7bd1ed0d067, - 0xed3b7ec7d6eded93, - 0xcc2edb85e2cccc17, - 0x422a578468424215, - 0x98b4c22d2c98985a, - 0xa4490e55eda4a4aa, - 0x285d8850752828a0, - 0x5cda31b8865c5c6d, - 0xf8933fed6bf8f8c7, - 0x8644a411c2868622, + 0x1bcfcff983d436cf, + 0xac2b2b6e5687452b, + 0xc57676e1ecb39776, + 0x328282e619b06482, + 0x7fd6d628b1a9fed6, + 0x6c1b1bc33677d81b, + 0xeeb5b574775bc1b5, + 0x86afafbe432911af, + 0xb56a6a1dd4df776a, + 0x5d5050eaa00dba50, + 0x094545578a4c1245, + 0xebf3f338fb18cbf3, + 0xc03030ad60f09d30, + 0x9befefc4c3742bef, + 0xfc3f3fda7ec3e53f, + 0x495555c7aa1c9255, + 0xb2a2a2db591079a2, + 0x8feaeae9c96503ea, + 0x8965656acaec0f65, + 0xd2baba036968b9ba, + 0xbc2f2f4a5e93652f, + 0x27c0c08e9de74ec0, + 0x5fdede60a181bede, + 0x701c1cfc386ce01c, + 0xd3fdfd46e72ebbfd, + 0x294d4d1f9a64524d, + 0x7292927639e0e492, + 0xc97575faeabc8f75, + 0x180606360c1e3006, + 0x128a8aae0998248a, + 0xf2b2b24b7940f9b2, + 0xbfe6e685d15963e6, + 0x380e0e7e1c36700e, + 0x7c1f1fe73e63f81f, + 0x95626255c4f73762, + 0x77d4d43ab5a3eed4, + 0x9aa8a8814d3229a8, + 0x6296965231f4c496, + 0xc3f9f962ef3a9bf9, + 0x33c5c5a397f666c5, + 0x942525104ab13525, + 0x795959abb220f259, + 0x2a8484d015ae5484, + 0xd57272c5e4a7b772, + 0xe43939ec72ddd539, + 0x2d4c4c1698615a4c, + 0x655e5e94bc3bca5e, + 0xfd78789ff085e778, + 0xe03838e570d8dd38, + 0x0a8c8c980586148c, + 0x63d1d117bfb2c6d1, + 0xaea5a5e4570b41a5, + 0xafe2e2a1d94d43e2, + 0x9961614ec2f82f61, + 0xf6b3b3427b45f1b3, + 0x8421213442a51521, + 0x4a9c9c0825d6949c, + 0x781e1eee3c66f01e, + 0x1143436186522243, + 0x3bc7c7b193fc76c7, + 0xd7fcfc4fe52bb3fc, + 0x1004042408142004, + 0x595151e3a208b251, + 0x5e9999252fc7bc99, + 0xa96d6d22dac44f6d, + 0x340d0d651a39680d, + 0xcffafa79e93583fa, + 0x5bdfdf69a384b6df, + 0xe57e7ea9fc9bd77e, + 0x9024241948b43d24, + 0xec3b3bfe76d7c53b, + 0x96abab9a4b3d31ab, + 0x1fcecef081d13ece, + 0x4411119922558811, + 0x068f8f8303890c8f, + 0x254e4e049c6b4a4e, + 0xe6b7b7667351d1b7, + 0x8bebebe0cb600beb, + 0xf03c3cc178ccfd3c, + 0x3e8181fd1fbf7c81, + 0x6a94944035fed494, + 0xfbf7f71cf30cebf7, + 0xdeb9b9186f67a1b9, + 0x4c13138b265f9813, + 0xb02c2c51589c7d2c, + 0x6bd3d305bbb8d6d3, + 0xbbe7e78cd35c6be7, + 0xa56e6e39dccb576e, + 0x37c4c4aa95f36ec4, + 0x0c03031b060f1803, + 0x455656dcac138a56, + 0x0d44445e88491a44, + 0xe17f7fa0fe9edf7f, + 0x9ea9a9884f3721a9, + 0xa82a2a6754824d2a, + 0xd6bbbb0a6b6db1bb, + 0x23c1c1879fe246c1, + 0x515353f1a602a253, + 0x57dcdc72a58baedc, + 0x2c0b0b531627580b, + 0x4e9d9d0127d39c9d, + 0xad6c6c2bd8c1476c, + 0xc43131a462f59531, + 0xcd7474f3e8b98774, + 0xfff6f615f109e3f6, + 0x0546464c8c430a46, + 0x8aacaca5452609ac, + 0x1e8989b50f973c89, + 0x501414b42844a014, + 0xa3e1e1badf425be1, + 0x581616a62c4eb016, + 0xe83a3af774d2cd3a, + 0xb9696906d2d06f69, + 0x24090941122d4809, + 0xdd7070d7e0ada770, + 0xe2b6b66f7154d9b6, + 0x67d0d01ebdb7ced0, + 0x93ededd6c77e3bed, + 0x17cccce285db2ecc, + 0x1542426884572a42, + 0x5a98982c2dc2b498, + 0xaaa4a4ed550e49a4, + 0xa028287550885d28, + 0x6d5c5c86b831da5c, + 0xc7f8f86bed3f93f8, + 0x228686c211a44486, ]; -pub static C6: [u64; 256] = [ - 0x6018c07830d81818, - 0x8c2305af46262323, - 0x3fc67ef991b8c6c6, - 0x87e8136fcdfbe8e8, - 0x26874ca113cb8787, - 0xdab8a9626d11b8b8, - 0x0401080502090101, - 0x214f426e9e0d4f4f, - 0xd836adee6c9b3636, - 0xa2a6590451ffa6a6, - 0x6fd2debdb90cd2d2, - 0xf3f5fb06f70ef5f5, - 0xf979ef80f2967979, - 0xa16f5fcede306f6f, - 0x7e91fcef3f6d9191, - 0x5552aa07a4f85252, - 0x9d6027fdc0476060, - 0xcabc89766535bcbc, - 0x569baccd2b379b9b, - 0x028e048c018a8e8e, - 0xb6a371155bd2a3a3, - 0x300c603c186c0c0c, - 0xf17bff8af6847b7b, - 0xd435b5e16a803535, - 0x741de8693af51d1d, - 0xa7e05347ddb3e0e0, - 0x7bd7f6acb321d7d7, - 0x2fc25eed999cc2c2, - 0xb82e6d965c432e2e, - 0x314b627a96294b4b, - 0xdffea321e15dfefe, - 0x41578216aed55757, - 0x5415a8412abd1515, - 0xc1779fb6eee87777, - 0xdc37a5eb6e923737, - 0xb3e57b56d79ee5e5, - 0x469f8cd923139f9f, - 0xe7f0d317fd23f0f0, - 0x354a6a7f94204a4a, - 0x4fda9e95a944dada, - 0x7d58fa25b0a25858, - 0x03c906ca8fcfc9c9, - 0xa429558d527c2929, - 0x280a5022145a0a0a, - 0xfeb1e14f7f50b1b1, - 0xbaa0691a5dc9a0a0, - 0xb16b7fdad6146b6b, - 0x2e855cab17d98585, - 0xcebd8173673cbdbd, - 0x695dd234ba8f5d5d, - 0x4010805020901010, - 0xf7f4f303f507f4f4, - 0x0bcb16c08bddcbcb, - 0xf83eedc67cd33e3e, - 0x140528110a2d0505, - 0x81671fe6ce786767, - 0xb7e47353d597e4e4, - 0x9c2725bb4e022727, - 0x1941325882734141, - 0x168b2c9d0ba78b8b, - 0xa6a7510153f6a7a7, - 0xe97dcf94fab27d7d, - 0x6e95dcfb37499595, - 0x47d88e9fad56d8d8, - 0xcbfb8b30eb70fbfb, - 0x9fee2371c1cdeeee, - 0xed7cc791f8bb7c7c, - 0x856617e3cc716666, - 0x53dda68ea77bdddd, - 0x5c17b84b2eaf1717, - 0x014702468e454747, - 0x429e84dc211a9e9e, - 0x0fca1ec589d4caca, - 0xb42d75995a582d2d, - 0xc6bf9179632ebfbf, - 0x1c07381b0e3f0707, - 0x8ead012347acadad, - 0x755aea2fb4b05a5a, - 0x36836cb51bef8383, - 0xcc3385ff66b63333, - 0x91633ff2c65c6363, - 0x0802100a04120202, - 0x92aa39384993aaaa, - 0xd971afa8e2de7171, - 0x07c80ecf8dc6c8c8, - 0x6419c87d32d11919, - 0x39497270923b4949, - 0x43d9869aaf5fd9d9, - 0xeff2c31df931f2f2, - 0xabe34b48dba8e3e3, - 0x715be22ab6b95b5b, - 0x1a8834920dbc8888, - 0x529aa4c8293e9a9a, - 0x98262dbe4c0b2626, - 0xc8328dfa64bf3232, - 0xfab0e94a7d59b0b0, - 0x83e91b6acff2e9e9, - 0x3c0f78331e770f0f, - 0x73d5e6a6b733d5d5, - 0x3a8074ba1df48080, - 0xc2be997c6127bebe, - 0x13cd26de87ebcdcd, - 0xd034bde468893434, - 0x3d487a7590324848, - 0xdbffab24e354ffff, - 0xf57af78ff48d7a7a, - 0x7a90f4ea3d649090, - 0x615fc23ebe9d5f5f, - 0x80201da0403d2020, - 0xbd6867d5d00f6868, - 0x681ad07234ca1a1a, - 0x82ae192c41b7aeae, - 0xeab4c95e757db4b4, - 0x4d549a19a8ce5454, - 0x7693ece53b7f9393, - 0x88220daa442f2222, - 0x8d6407e9c8636464, - 0xe3f1db12ff2af1f1, - 0xd173bfa2e6cc7373, - 0x4812905a24821212, - 0x1d403a5d807a4040, - 0x2008402810480808, - 0x2bc356e89b95c3c3, - 0x97ec337bc5dfecec, - 0x4bdb9690ab4ddbdb, - 0xbea1611f5fc0a1a1, - 0x0e8d1c8307918d8d, - 0xf43df5c97ac83d3d, - 0x6697ccf1335b9797, +pub const C6: [u64; 256] = [ + 0x1818d83078c01860, + 0x23232646af05238c, + 0xc6c6b891f97ec63f, + 0xe8e8fbcd6f13e887, + 0x8787cb13a14c8726, + 0xb8b8116d62a9b8da, + 0x0101090205080104, + 0x4f4f0d9e6e424f21, + 0x36369b6ceead36d8, + 0xa6a6ff510459a6a2, + 0xd2d20cb9bdded26f, + 0xf5f50ef706fbf5f3, + 0x797996f280ef79f9, + 0x6f6f30dece5f6fa1, + 0x91916d3feffc917e, + 0x5252f8a407aa5255, + 0x606047c0fd27609d, + 0xbcbc35657689bcca, + 0x9b9b372bcdac9b56, + 0x8e8e8a018c048e02, + 0xa3a3d25b1571a3b6, + 0x0c0c6c183c600c30, + 0x7b7b84f68aff7bf1, + 0x3535806ae1b535d4, + 0x1d1df53a69e81d74, + 0xe0e0b3dd4753e0a7, + 0xd7d721b3acf6d77b, + 0xc2c29c99ed5ec22f, + 0x2e2e435c966d2eb8, + 0x4b4b29967a624b31, + 0xfefe5de121a3fedf, + 0x5757d5ae16825741, + 0x1515bd2a41a81554, + 0x7777e8eeb69f77c1, + 0x3737926eeba537dc, + 0xe5e59ed7567be5b3, + 0x9f9f1323d98c9f46, + 0xf0f023fd17d3f0e7, + 0x4a4a20947f6a4a35, + 0xdada44a9959eda4f, + 0x5858a2b025fa587d, + 0xc9c9cf8fca06c903, + 0x29297c528d5529a4, + 0x0a0a5a1422500a28, + 0xb1b1507f4fe1b1fe, + 0xa0a0c95d1a69a0ba, + 0x6b6b14d6da7f6bb1, + 0x8585d917ab5c852e, + 0xbdbd3c677381bdce, + 0x5d5d8fba34d25d69, + 0x1010902050801040, + 0xf4f407f503f3f4f7, + 0xcbcbdd8bc016cb0b, + 0x3e3ed37cc6ed3ef8, + 0x05052d0a11280514, + 0x676778cee61f6781, + 0xe4e497d55373e4b7, + 0x2727024ebb25279c, + 0x4141738258324119, + 0x8b8ba70b9d2c8b16, + 0xa7a7f6530151a7a6, + 0x7d7db2fa94cf7de9, + 0x95954937fbdc956e, + 0xd8d856ad9f8ed847, + 0xfbfb70eb308bfbcb, + 0xeeeecdc17123ee9f, + 0x7c7cbbf891c77ced, + 0x666671cce3176685, + 0xdddd7ba78ea6dd53, + 0x1717af2e4bb8175c, + 0x4747458e46024701, + 0x9e9e1a21dc849e42, + 0xcacad489c51eca0f, + 0x2d2d585a99752db4, + 0xbfbf2e637991bfc6, + 0x07073f0e1b38071c, + 0xadadac472301ad8e, + 0x5a5ab0b42fea5a75, + 0x8383ef1bb56c8336, + 0x3333b666ff8533cc, + 0x63635cc6f23f6391, + 0x020212040a100208, + 0xaaaa93493839aa92, + 0x7171dee2a8af71d9, + 0xc8c8c68dcf0ec807, + 0x1919d1327dc81964, + 0x49493b9270724939, + 0xd9d95faf9a86d943, + 0xf2f231f91dc3f2ef, + 0xe3e3a8db484be3ab, + 0x5b5bb9b62ae25b71, + 0x8888bc0d9234881a, + 0x9a9a3e29c8a49a52, + 0x26260b4cbe2d2698, + 0x3232bf64fa8d32c8, + 0xb0b0597d4ae9b0fa, + 0xe9e9f2cf6a1be983, + 0x0f0f771e33780f3c, + 0xd5d533b7a6e6d573, + 0x8080f41dba74803a, + 0xbebe27617c99bec2, + 0xcdcdeb87de26cd13, + 0x34348968e4bd34d0, + 0x48483290757a483d, + 0xffff54e324abffdb, + 0x7a7a8df48ff77af5, + 0x9090643deaf4907a, + 0x5f5f9dbe3ec25f61, + 0x20203d40a01d2080, + 0x68680fd0d56768bd, + 0x1a1aca3472d01a68, + 0xaeaeb7412c19ae82, + 0xb4b47d755ec9b4ea, + 0x5454cea8199a544d, + 0x93937f3be5ec9376, + 0x22222f44aa0d2288, + 0x646463c8e907648d, + 0xf1f12aff12dbf1e3, + 0x7373cce6a2bf73d1, + 0x121282245a901248, + 0x40407a805d3a401d, + 0x0808481028400820, + 0xc3c3959be856c32b, + 0xececdfc57b33ec97, + 0xdbdb4dab9096db4b, + 0xa1a1c05f1f61a1be, + 0x8d8d9107831c8d0e, + 0x3d3dc87ac9f53df4, + 0x97975b33f1cc9766, 0x0000000000000000, - 0x1bcf36d483f9cfcf, - 0xac2b4587566e2b2b, - 0xc57697b3ece17676, - 0x328264b019e68282, - 0x7fd6fea9b128d6d6, - 0x6c1bd87736c31b1b, - 0xeeb5c15b7774b5b5, - 0x86af112943beafaf, - 0xb56a77dfd41d6a6a, - 0x5d50ba0da0ea5050, - 0x0945124c8a574545, - 0xebf3cb18fb38f3f3, - 0xc0309df060ad3030, - 0x9bef2b74c3c4efef, - 0xfc3fe5c37eda3f3f, - 0x4955921caac75555, - 0xb2a2791059dba2a2, - 0x8fea0365c9e9eaea, - 0x89650fecca6a6565, - 0xd2bab9686903baba, - 0xbc2f65935e4a2f2f, - 0x27c04ee79d8ec0c0, - 0x5fdebe81a160dede, - 0x701ce06c38fc1c1c, - 0xd3fdbb2ee746fdfd, - 0x294d52649a1f4d4d, - 0x7292e4e039769292, - 0xc9758fbceafa7575, - 0x1806301e0c360606, - 0x128a249809ae8a8a, - 0xf2b2f940794bb2b2, - 0xbfe66359d185e6e6, - 0x380e70361c7e0e0e, - 0x7c1ff8633ee71f1f, - 0x956237f7c4556262, - 0x77d4eea3b53ad4d4, - 0x9aa829324d81a8a8, - 0x6296c4f431529696, - 0xc3f99b3aef62f9f9, - 0x33c566f697a3c5c5, - 0x942535b14a102525, - 0x7959f220b2ab5959, - 0x2a8454ae15d08484, - 0xd572b7a7e4c57272, - 0xe439d5dd72ec3939, - 0x2d4c5a6198164c4c, - 0x655eca3bbc945e5e, - 0xfd78e785f09f7878, - 0xe038ddd870e53838, - 0x0a8c148605988c8c, - 0x63d1c6b2bf17d1d1, - 0xaea5410b57e4a5a5, - 0xafe2434dd9a1e2e2, - 0x99612ff8c24e6161, - 0xf6b3f1457b42b3b3, - 0x842115a542342121, - 0x4a9c94d625089c9c, - 0x781ef0663cee1e1e, - 0x1143225286614343, - 0x3bc776fc93b1c7c7, - 0xd7fcb32be54ffcfc, - 0x1004201408240404, - 0x5951b208a2e35151, - 0x5e99bcc72f259999, - 0xa96d4fc4da226d6d, - 0x340d68391a650d0d, - 0xcffa8335e979fafa, - 0x5bdfb684a369dfdf, - 0xe57ed79bfca97e7e, - 0x90243db448192424, - 0xec3bc5d776fe3b3b, - 0x96ab313d4b9aabab, - 0x1fce3ed181f0cece, - 0x4411885522991111, - 0x068f0c8903838f8f, - 0x254e4a6b9c044e4e, - 0xe6b7d1517366b7b7, - 0x8beb0b60cbe0ebeb, - 0xf03cfdcc78c13c3c, - 0x3e817cbf1ffd8181, - 0x6a94d4fe35409494, - 0xfbf7eb0cf31cf7f7, - 0xdeb9a1676f18b9b9, - 0x4c13985f268b1313, - 0xb02c7d9c58512c2c, - 0x6bd3d6b8bb05d3d3, - 0xbbe76b5cd38ce7e7, - 0xa56e57cbdc396e6e, - 0x37c46ef395aac4c4, - 0x0c03180f061b0303, - 0x45568a13acdc5656, - 0x0d441a49885e4444, - 0xe17fdf9efea07f7f, - 0x9ea921374f88a9a9, - 0xa82a4d8254672a2a, - 0xd6bbb16d6b0abbbb, - 0x23c146e29f87c1c1, - 0x5153a202a6f15353, - 0x57dcae8ba572dcdc, - 0x2c0b582716530b0b, - 0x4e9d9cd327019d9d, - 0xad6c47c1d82b6c6c, - 0xc43195f562a43131, - 0xcd7487b9e8f37474, - 0xfff6e309f115f6f6, - 0x05460a438c4c4646, - 0x8aac092645a5acac, - 0x1e893c970fb58989, - 0x5014a04428b41414, - 0xa3e15b42dfbae1e1, - 0x5816b04e2ca61616, - 0xe83acdd274f73a3a, - 0xb9696fd0d2066969, - 0x2409482d12410909, - 0xdd70a7ade0d77070, - 0xe2b6d954716fb6b6, - 0x67d0ceb7bd1ed0d0, - 0x93ed3b7ec7d6eded, - 0x17cc2edb85e2cccc, - 0x15422a5784684242, - 0x5a98b4c22d2c9898, - 0xaaa4490e55eda4a4, - 0xa0285d8850752828, - 0x6d5cda31b8865c5c, - 0xc7f8933fed6bf8f8, - 0x228644a411c28686, + 0xcfcff983d436cf1b, + 0x2b2b6e5687452bac, + 0x7676e1ecb39776c5, + 0x8282e619b0648232, + 0xd6d628b1a9fed67f, + 0x1b1bc33677d81b6c, + 0xb5b574775bc1b5ee, + 0xafafbe432911af86, + 0x6a6a1dd4df776ab5, + 0x5050eaa00dba505d, + 0x4545578a4c124509, + 0xf3f338fb18cbf3eb, + 0x3030ad60f09d30c0, + 0xefefc4c3742bef9b, + 0x3f3fda7ec3e53ffc, + 0x5555c7aa1c925549, + 0xa2a2db591079a2b2, + 0xeaeae9c96503ea8f, + 0x65656acaec0f6589, + 0xbaba036968b9bad2, + 0x2f2f4a5e93652fbc, + 0xc0c08e9de74ec027, + 0xdede60a181bede5f, + 0x1c1cfc386ce01c70, + 0xfdfd46e72ebbfdd3, + 0x4d4d1f9a64524d29, + 0x92927639e0e49272, + 0x7575faeabc8f75c9, + 0x0606360c1e300618, + 0x8a8aae0998248a12, + 0xb2b24b7940f9b2f2, + 0xe6e685d15963e6bf, + 0x0e0e7e1c36700e38, + 0x1f1fe73e63f81f7c, + 0x626255c4f7376295, + 0xd4d43ab5a3eed477, + 0xa8a8814d3229a89a, + 0x96965231f4c49662, + 0xf9f962ef3a9bf9c3, + 0xc5c5a397f666c533, + 0x2525104ab1352594, + 0x5959abb220f25979, + 0x8484d015ae54842a, + 0x7272c5e4a7b772d5, + 0x3939ec72ddd539e4, + 0x4c4c1698615a4c2d, + 0x5e5e94bc3bca5e65, + 0x78789ff085e778fd, + 0x3838e570d8dd38e0, + 0x8c8c980586148c0a, + 0xd1d117bfb2c6d163, + 0xa5a5e4570b41a5ae, + 0xe2e2a1d94d43e2af, + 0x61614ec2f82f6199, + 0xb3b3427b45f1b3f6, + 0x21213442a5152184, + 0x9c9c0825d6949c4a, + 0x1e1eee3c66f01e78, + 0x4343618652224311, + 0xc7c7b193fc76c73b, + 0xfcfc4fe52bb3fcd7, + 0x0404240814200410, + 0x5151e3a208b25159, + 0x9999252fc7bc995e, + 0x6d6d22dac44f6da9, + 0x0d0d651a39680d34, + 0xfafa79e93583facf, + 0xdfdf69a384b6df5b, + 0x7e7ea9fc9bd77ee5, + 0x24241948b43d2490, + 0x3b3bfe76d7c53bec, + 0xabab9a4b3d31ab96, + 0xcecef081d13ece1f, + 0x1111992255881144, + 0x8f8f8303890c8f06, + 0x4e4e049c6b4a4e25, + 0xb7b7667351d1b7e6, + 0xebebe0cb600beb8b, + 0x3c3cc178ccfd3cf0, + 0x8181fd1fbf7c813e, + 0x94944035fed4946a, + 0xf7f71cf30cebf7fb, + 0xb9b9186f67a1b9de, + 0x13138b265f98134c, + 0x2c2c51589c7d2cb0, + 0xd3d305bbb8d6d36b, + 0xe7e78cd35c6be7bb, + 0x6e6e39dccb576ea5, + 0xc4c4aa95f36ec437, + 0x03031b060f18030c, + 0x5656dcac138a5645, + 0x44445e88491a440d, + 0x7f7fa0fe9edf7fe1, + 0xa9a9884f3721a99e, + 0x2a2a6754824d2aa8, + 0xbbbb0a6b6db1bbd6, + 0xc1c1879fe246c123, + 0x5353f1a602a25351, + 0xdcdc72a58baedc57, + 0x0b0b531627580b2c, + 0x9d9d0127d39c9d4e, + 0x6c6c2bd8c1476cad, + 0x3131a462f59531c4, + 0x7474f3e8b98774cd, + 0xf6f615f109e3f6ff, + 0x46464c8c430a4605, + 0xacaca5452609ac8a, + 0x8989b50f973c891e, + 0x1414b42844a01450, + 0xe1e1badf425be1a3, + 0x1616a62c4eb01658, + 0x3a3af774d2cd3ae8, + 0x696906d2d06f69b9, + 0x090941122d480924, + 0x7070d7e0ada770dd, + 0xb6b66f7154d9b6e2, + 0xd0d01ebdb7ced067, + 0xededd6c77e3bed93, + 0xcccce285db2ecc17, + 0x42426884572a4215, + 0x98982c2dc2b4985a, + 0xa4a4ed550e49a4aa, + 0x28287550885d28a0, + 0x5c5c86b831da5c6d, + 0xf8f86bed3f93f8c7, + 0x8686c211a4448622, ]; -pub static C7: [u64; 256] = [ - 0x186018c07830d818, - 0x238c2305af462623, - 0xc63fc67ef991b8c6, - 0xe887e8136fcdfbe8, - 0x8726874ca113cb87, - 0xb8dab8a9626d11b8, - 0x0104010805020901, - 0x4f214f426e9e0d4f, - 0x36d836adee6c9b36, - 0xa6a2a6590451ffa6, - 0xd26fd2debdb90cd2, - 0xf5f3f5fb06f70ef5, - 0x79f979ef80f29679, - 0x6fa16f5fcede306f, - 0x917e91fcef3f6d91, - 0x525552aa07a4f852, - 0x609d6027fdc04760, - 0xbccabc89766535bc, - 0x9b569baccd2b379b, - 0x8e028e048c018a8e, - 0xa3b6a371155bd2a3, - 0x0c300c603c186c0c, - 0x7bf17bff8af6847b, - 0x35d435b5e16a8035, - 0x1d741de8693af51d, - 0xe0a7e05347ddb3e0, - 0xd77bd7f6acb321d7, - 0xc22fc25eed999cc2, - 0x2eb82e6d965c432e, - 0x4b314b627a96294b, - 0xfedffea321e15dfe, - 0x5741578216aed557, - 0x155415a8412abd15, - 0x77c1779fb6eee877, - 0x37dc37a5eb6e9237, - 0xe5b3e57b56d79ee5, - 0x9f469f8cd923139f, - 0xf0e7f0d317fd23f0, - 0x4a354a6a7f94204a, - 0xda4fda9e95a944da, - 0x587d58fa25b0a258, - 0xc903c906ca8fcfc9, - 0x29a429558d527c29, - 0x0a280a5022145a0a, - 0xb1feb1e14f7f50b1, - 0xa0baa0691a5dc9a0, - 0x6bb16b7fdad6146b, - 0x852e855cab17d985, - 0xbdcebd8173673cbd, - 0x5d695dd234ba8f5d, - 0x1040108050209010, - 0xf4f7f4f303f507f4, - 0xcb0bcb16c08bddcb, - 0x3ef83eedc67cd33e, - 0x05140528110a2d05, - 0x6781671fe6ce7867, - 0xe4b7e47353d597e4, - 0x279c2725bb4e0227, - 0x4119413258827341, - 0x8b168b2c9d0ba78b, - 0xa7a6a7510153f6a7, - 0x7de97dcf94fab27d, - 0x956e95dcfb374995, - 0xd847d88e9fad56d8, - 0xfbcbfb8b30eb70fb, - 0xee9fee2371c1cdee, - 0x7ced7cc791f8bb7c, - 0x66856617e3cc7166, - 0xdd53dda68ea77bdd, - 0x175c17b84b2eaf17, - 0x47014702468e4547, - 0x9e429e84dc211a9e, - 0xca0fca1ec589d4ca, - 0x2db42d75995a582d, - 0xbfc6bf9179632ebf, - 0x071c07381b0e3f07, - 0xad8ead012347acad, - 0x5a755aea2fb4b05a, - 0x8336836cb51bef83, - 0x33cc3385ff66b633, - 0x6391633ff2c65c63, - 0x020802100a041202, - 0xaa92aa39384993aa, - 0x71d971afa8e2de71, - 0xc807c80ecf8dc6c8, - 0x196419c87d32d119, - 0x4939497270923b49, - 0xd943d9869aaf5fd9, - 0xf2eff2c31df931f2, - 0xe3abe34b48dba8e3, - 0x5b715be22ab6b95b, - 0x881a8834920dbc88, - 0x9a529aa4c8293e9a, - 0x2698262dbe4c0b26, - 0x32c8328dfa64bf32, - 0xb0fab0e94a7d59b0, - 0xe983e91b6acff2e9, - 0x0f3c0f78331e770f, - 0xd573d5e6a6b733d5, - 0x803a8074ba1df480, - 0xbec2be997c6127be, - 0xcd13cd26de87ebcd, - 0x34d034bde4688934, - 0x483d487a75903248, - 0xffdbffab24e354ff, - 0x7af57af78ff48d7a, - 0x907a90f4ea3d6490, - 0x5f615fc23ebe9d5f, - 0x2080201da0403d20, - 0x68bd6867d5d00f68, - 0x1a681ad07234ca1a, - 0xae82ae192c41b7ae, - 0xb4eab4c95e757db4, - 0x544d549a19a8ce54, - 0x937693ece53b7f93, - 0x2288220daa442f22, - 0x648d6407e9c86364, - 0xf1e3f1db12ff2af1, - 0x73d173bfa2e6cc73, - 0x124812905a248212, - 0x401d403a5d807a40, - 0x0820084028104808, - 0xc32bc356e89b95c3, - 0xec97ec337bc5dfec, - 0xdb4bdb9690ab4ddb, - 0xa1bea1611f5fc0a1, - 0x8d0e8d1c8307918d, - 0x3df43df5c97ac83d, - 0x976697ccf1335b97, +pub const C7: [u64; 256] = [ + 0x18d83078c0186018, + 0x232646af05238c23, + 0xc6b891f97ec63fc6, + 0xe8fbcd6f13e887e8, + 0x87cb13a14c872687, + 0xb8116d62a9b8dab8, + 0x0109020508010401, + 0x4f0d9e6e424f214f, + 0x369b6ceead36d836, + 0xa6ff510459a6a2a6, + 0xd20cb9bdded26fd2, + 0xf50ef706fbf5f3f5, + 0x7996f280ef79f979, + 0x6f30dece5f6fa16f, + 0x916d3feffc917e91, + 0x52f8a407aa525552, + 0x6047c0fd27609d60, + 0xbc35657689bccabc, + 0x9b372bcdac9b569b, + 0x8e8a018c048e028e, + 0xa3d25b1571a3b6a3, + 0x0c6c183c600c300c, + 0x7b84f68aff7bf17b, + 0x35806ae1b535d435, + 0x1df53a69e81d741d, + 0xe0b3dd4753e0a7e0, + 0xd721b3acf6d77bd7, + 0xc29c99ed5ec22fc2, + 0x2e435c966d2eb82e, + 0x4b29967a624b314b, + 0xfe5de121a3fedffe, + 0x57d5ae1682574157, + 0x15bd2a41a8155415, + 0x77e8eeb69f77c177, + 0x37926eeba537dc37, + 0xe59ed7567be5b3e5, + 0x9f1323d98c9f469f, + 0xf023fd17d3f0e7f0, + 0x4a20947f6a4a354a, + 0xda44a9959eda4fda, + 0x58a2b025fa587d58, + 0xc9cf8fca06c903c9, + 0x297c528d5529a429, + 0x0a5a1422500a280a, + 0xb1507f4fe1b1feb1, + 0xa0c95d1a69a0baa0, + 0x6b14d6da7f6bb16b, + 0x85d917ab5c852e85, + 0xbd3c677381bdcebd, + 0x5d8fba34d25d695d, + 0x1090205080104010, + 0xf407f503f3f4f7f4, + 0xcbdd8bc016cb0bcb, + 0x3ed37cc6ed3ef83e, + 0x052d0a1128051405, + 0x6778cee61f678167, + 0xe497d55373e4b7e4, + 0x27024ebb25279c27, + 0x4173825832411941, + 0x8ba70b9d2c8b168b, + 0xa7f6530151a7a6a7, + 0x7db2fa94cf7de97d, + 0x954937fbdc956e95, + 0xd856ad9f8ed847d8, + 0xfb70eb308bfbcbfb, + 0xeecdc17123ee9fee, + 0x7cbbf891c77ced7c, + 0x6671cce317668566, + 0xdd7ba78ea6dd53dd, + 0x17af2e4bb8175c17, + 0x47458e4602470147, + 0x9e1a21dc849e429e, + 0xcad489c51eca0fca, + 0x2d585a99752db42d, + 0xbf2e637991bfc6bf, + 0x073f0e1b38071c07, + 0xadac472301ad8ead, + 0x5ab0b42fea5a755a, + 0x83ef1bb56c833683, + 0x33b666ff8533cc33, + 0x635cc6f23f639163, + 0x0212040a10020802, + 0xaa93493839aa92aa, + 0x71dee2a8af71d971, + 0xc8c68dcf0ec807c8, + 0x19d1327dc8196419, + 0x493b927072493949, + 0xd95faf9a86d943d9, + 0xf231f91dc3f2eff2, + 0xe3a8db484be3abe3, + 0x5bb9b62ae25b715b, + 0x88bc0d9234881a88, + 0x9a3e29c8a49a529a, + 0x260b4cbe2d269826, + 0x32bf64fa8d32c832, + 0xb0597d4ae9b0fab0, + 0xe9f2cf6a1be983e9, + 0x0f771e33780f3c0f, + 0xd533b7a6e6d573d5, + 0x80f41dba74803a80, + 0xbe27617c99bec2be, + 0xcdeb87de26cd13cd, + 0x348968e4bd34d034, + 0x483290757a483d48, + 0xff54e324abffdbff, + 0x7a8df48ff77af57a, + 0x90643deaf4907a90, + 0x5f9dbe3ec25f615f, + 0x203d40a01d208020, + 0x680fd0d56768bd68, + 0x1aca3472d01a681a, + 0xaeb7412c19ae82ae, + 0xb47d755ec9b4eab4, + 0x54cea8199a544d54, + 0x937f3be5ec937693, + 0x222f44aa0d228822, + 0x6463c8e907648d64, + 0xf12aff12dbf1e3f1, + 0x73cce6a2bf73d173, + 0x1282245a90124812, + 0x407a805d3a401d40, + 0x0848102840082008, + 0xc3959be856c32bc3, + 0xecdfc57b33ec97ec, + 0xdb4dab9096db4bdb, + 0xa1c05f1f61a1bea1, + 0x8d9107831c8d0e8d, + 0x3dc87ac9f53df43d, + 0x975b33f1cc976697, 0x0000000000000000, - 0xcf1bcf36d483f9cf, - 0x2bac2b4587566e2b, - 0x76c57697b3ece176, - 0x82328264b019e682, - 0xd67fd6fea9b128d6, - 0x1b6c1bd87736c31b, - 0xb5eeb5c15b7774b5, - 0xaf86af112943beaf, - 0x6ab56a77dfd41d6a, - 0x505d50ba0da0ea50, - 0x450945124c8a5745, - 0xf3ebf3cb18fb38f3, - 0x30c0309df060ad30, - 0xef9bef2b74c3c4ef, - 0x3ffc3fe5c37eda3f, - 0x554955921caac755, - 0xa2b2a2791059dba2, - 0xea8fea0365c9e9ea, - 0x6589650fecca6a65, - 0xbad2bab9686903ba, - 0x2fbc2f65935e4a2f, - 0xc027c04ee79d8ec0, - 0xde5fdebe81a160de, - 0x1c701ce06c38fc1c, - 0xfdd3fdbb2ee746fd, - 0x4d294d52649a1f4d, - 0x927292e4e0397692, - 0x75c9758fbceafa75, - 0x061806301e0c3606, - 0x8a128a249809ae8a, - 0xb2f2b2f940794bb2, - 0xe6bfe66359d185e6, - 0x0e380e70361c7e0e, - 0x1f7c1ff8633ee71f, - 0x62956237f7c45562, - 0xd477d4eea3b53ad4, - 0xa89aa829324d81a8, - 0x966296c4f4315296, - 0xf9c3f99b3aef62f9, - 0xc533c566f697a3c5, - 0x25942535b14a1025, - 0x597959f220b2ab59, - 0x842a8454ae15d084, - 0x72d572b7a7e4c572, - 0x39e439d5dd72ec39, - 0x4c2d4c5a6198164c, - 0x5e655eca3bbc945e, - 0x78fd78e785f09f78, - 0x38e038ddd870e538, - 0x8c0a8c148605988c, - 0xd163d1c6b2bf17d1, - 0xa5aea5410b57e4a5, - 0xe2afe2434dd9a1e2, - 0x6199612ff8c24e61, - 0xb3f6b3f1457b42b3, - 0x21842115a5423421, - 0x9c4a9c94d625089c, - 0x1e781ef0663cee1e, - 0x4311432252866143, - 0xc73bc776fc93b1c7, - 0xfcd7fcb32be54ffc, - 0x0410042014082404, - 0x515951b208a2e351, - 0x995e99bcc72f2599, - 0x6da96d4fc4da226d, - 0x0d340d68391a650d, - 0xfacffa8335e979fa, - 0xdf5bdfb684a369df, - 0x7ee57ed79bfca97e, - 0x2490243db4481924, - 0x3bec3bc5d776fe3b, - 0xab96ab313d4b9aab, - 0xce1fce3ed181f0ce, - 0x1144118855229911, - 0x8f068f0c8903838f, - 0x4e254e4a6b9c044e, - 0xb7e6b7d1517366b7, - 0xeb8beb0b60cbe0eb, - 0x3cf03cfdcc78c13c, - 0x813e817cbf1ffd81, - 0x946a94d4fe354094, - 0xf7fbf7eb0cf31cf7, - 0xb9deb9a1676f18b9, - 0x134c13985f268b13, - 0x2cb02c7d9c58512c, - 0xd36bd3d6b8bb05d3, - 0xe7bbe76b5cd38ce7, - 0x6ea56e57cbdc396e, - 0xc437c46ef395aac4, - 0x030c03180f061b03, - 0x5645568a13acdc56, - 0x440d441a49885e44, - 0x7fe17fdf9efea07f, - 0xa99ea921374f88a9, - 0x2aa82a4d8254672a, - 0xbbd6bbb16d6b0abb, - 0xc123c146e29f87c1, - 0x535153a202a6f153, - 0xdc57dcae8ba572dc, - 0x0b2c0b582716530b, - 0x9d4e9d9cd327019d, - 0x6cad6c47c1d82b6c, - 0x31c43195f562a431, - 0x74cd7487b9e8f374, - 0xf6fff6e309f115f6, - 0x4605460a438c4c46, - 0xac8aac092645a5ac, - 0x891e893c970fb589, - 0x145014a04428b414, - 0xe1a3e15b42dfbae1, - 0x165816b04e2ca616, - 0x3ae83acdd274f73a, - 0x69b9696fd0d20669, - 0x092409482d124109, - 0x70dd70a7ade0d770, - 0xb6e2b6d954716fb6, - 0xd067d0ceb7bd1ed0, - 0xed93ed3b7ec7d6ed, - 0xcc17cc2edb85e2cc, - 0x4215422a57846842, - 0x985a98b4c22d2c98, - 0xa4aaa4490e55eda4, - 0x28a0285d88507528, - 0x5c6d5cda31b8865c, - 0xf8c7f8933fed6bf8, - 0x86228644a411c286, + 0xcff983d436cf1bcf, + 0x2b6e5687452bac2b, + 0x76e1ecb39776c576, + 0x82e619b064823282, + 0xd628b1a9fed67fd6, + 0x1bc33677d81b6c1b, + 0xb574775bc1b5eeb5, + 0xafbe432911af86af, + 0x6a1dd4df776ab56a, + 0x50eaa00dba505d50, + 0x45578a4c12450945, + 0xf338fb18cbf3ebf3, + 0x30ad60f09d30c030, + 0xefc4c3742bef9bef, + 0x3fda7ec3e53ffc3f, + 0x55c7aa1c92554955, + 0xa2db591079a2b2a2, + 0xeae9c96503ea8fea, + 0x656acaec0f658965, + 0xba036968b9bad2ba, + 0x2f4a5e93652fbc2f, + 0xc08e9de74ec027c0, + 0xde60a181bede5fde, + 0x1cfc386ce01c701c, + 0xfd46e72ebbfdd3fd, + 0x4d1f9a64524d294d, + 0x927639e0e4927292, + 0x75faeabc8f75c975, + 0x06360c1e30061806, + 0x8aae0998248a128a, + 0xb24b7940f9b2f2b2, + 0xe685d15963e6bfe6, + 0x0e7e1c36700e380e, + 0x1fe73e63f81f7c1f, + 0x6255c4f737629562, + 0xd43ab5a3eed477d4, + 0xa8814d3229a89aa8, + 0x965231f4c4966296, + 0xf962ef3a9bf9c3f9, + 0xc5a397f666c533c5, + 0x25104ab135259425, + 0x59abb220f2597959, + 0x84d015ae54842a84, + 0x72c5e4a7b772d572, + 0x39ec72ddd539e439, + 0x4c1698615a4c2d4c, + 0x5e94bc3bca5e655e, + 0x789ff085e778fd78, + 0x38e570d8dd38e038, + 0x8c980586148c0a8c, + 0xd117bfb2c6d163d1, + 0xa5e4570b41a5aea5, + 0xe2a1d94d43e2afe2, + 0x614ec2f82f619961, + 0xb3427b45f1b3f6b3, + 0x213442a515218421, + 0x9c0825d6949c4a9c, + 0x1eee3c66f01e781e, + 0x4361865222431143, + 0xc7b193fc76c73bc7, + 0xfc4fe52bb3fcd7fc, + 0x0424081420041004, + 0x51e3a208b2515951, + 0x99252fc7bc995e99, + 0x6d22dac44f6da96d, + 0x0d651a39680d340d, + 0xfa79e93583facffa, + 0xdf69a384b6df5bdf, + 0x7ea9fc9bd77ee57e, + 0x241948b43d249024, + 0x3bfe76d7c53bec3b, + 0xab9a4b3d31ab96ab, + 0xcef081d13ece1fce, + 0x1199225588114411, + 0x8f8303890c8f068f, + 0x4e049c6b4a4e254e, + 0xb7667351d1b7e6b7, + 0xebe0cb600beb8beb, + 0x3cc178ccfd3cf03c, + 0x81fd1fbf7c813e81, + 0x944035fed4946a94, + 0xf71cf30cebf7fbf7, + 0xb9186f67a1b9deb9, + 0x138b265f98134c13, + 0x2c51589c7d2cb02c, + 0xd305bbb8d6d36bd3, + 0xe78cd35c6be7bbe7, + 0x6e39dccb576ea56e, + 0xc4aa95f36ec437c4, + 0x031b060f18030c03, + 0x56dcac138a564556, + 0x445e88491a440d44, + 0x7fa0fe9edf7fe17f, + 0xa9884f3721a99ea9, + 0x2a6754824d2aa82a, + 0xbb0a6b6db1bbd6bb, + 0xc1879fe246c123c1, + 0x53f1a602a2535153, + 0xdc72a58baedc57dc, + 0x0b531627580b2c0b, + 0x9d0127d39c9d4e9d, + 0x6c2bd8c1476cad6c, + 0x31a462f59531c431, + 0x74f3e8b98774cd74, + 0xf615f109e3f6fff6, + 0x464c8c430a460546, + 0xaca5452609ac8aac, + 0x89b50f973c891e89, + 0x14b42844a0145014, + 0xe1badf425be1a3e1, + 0x16a62c4eb0165816, + 0x3af774d2cd3ae83a, + 0x6906d2d06f69b969, + 0x0941122d48092409, + 0x70d7e0ada770dd70, + 0xb66f7154d9b6e2b6, + 0xd01ebdb7ced067d0, + 0xedd6c77e3bed93ed, + 0xcce285db2ecc17cc, + 0x426884572a421542, + 0x982c2dc2b4985a98, + 0xa4ed550e49a4aaa4, + 0x287550885d28a028, + 0x5c86b831da5c6d5c, + 0xf86bed3f93f8c7f8, + 0x86c211a444862286, ]; diff --git a/whirlpool/src/lib.rs b/whirlpool/src/lib.rs index e2e313f66..54197e8f2 100644 --- a/whirlpool/src/lib.rs +++ b/whirlpool/src/lib.rs @@ -37,163 +37,140 @@ #![no_std] #![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_root_url = "https://docs.rs/whirlpool/0.10.0" )] -#![deny(unsafe_code)] #![warn(missing_docs, rust_2018_idioms)] -#[cfg(feature = "std")] -extern crate std; - -#[cfg(feature = "asm")] -use whirlpool_asm as utils; +pub use digest::{self, Digest}; #[cfg(not(feature = "asm"))] -mod utils; - -#[cfg(not(feature = "asm"))] -mod consts; - -pub use digest::Digest; +mod compress; -use crate::utils::compress; +#[cfg(feature = "asm")] +use whirlpool_asm as compress; + +use compress::compress; + +use core::{fmt, slice::from_ref}; +use digest::{ + block_buffer::Eager, + core_api::{ + AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore, + OutputSizeUser, Reset, UpdateCore, + }, + generic_array::typenum::{Unsigned, U64}, + HashMarker, Output, +}; + +/// Core Whirlpool hasher state. +#[derive(Clone)] +pub struct WhirlpoolCore { + bit_len: [u64; 4], + state: [u64; 8], +} -use block_buffer::{block_padding::Iso7816, BlockBuffer}; -use digest::{consts::U64, generic_array::GenericArray}; -use digest::{BlockInput, FixedOutputDirty, Reset, Update}; +impl HashMarker for WhirlpoolCore {} -type BlockSize = U64; +impl BlockSizeUser for WhirlpoolCore { + type BlockSize = U64; +} -/// Structure representing the state of a Whirlpool computation -#[derive(Clone)] -pub struct Whirlpool { - bit_length: [u8; 32], - buffer: BlockBuffer, - #[cfg(not(feature = "asm"))] - hash: [u64; 8], - #[cfg(feature = "asm")] - hash: [u8; 64], +impl BufferKindUser for WhirlpoolCore { + type BufferKind = Eager; } -impl Default for Whirlpool { - fn default() -> Self { - Self { - bit_length: [0u8; 32], - buffer: BlockBuffer::default(), - #[cfg(not(feature = "asm"))] - hash: [0u64; 8], - #[cfg(feature = "asm")] - hash: [0u8; 64], - } - } +impl OutputSizeUser for WhirlpoolCore { + type OutputSize = U64; } -fn convert(block: &GenericArray) -> &[u8; 64] { - #[allow(unsafe_code)] - unsafe { - &*(block.as_ptr() as *const [u8; 64]) +impl UpdateCore for WhirlpoolCore { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + let block_bits = 8 * BLOCK_SIZE as u64; + self.update_len(block_bits * (blocks.len() as u64)); + compress(&mut self.state, convert(blocks)); } } -impl Whirlpool { - #![cfg_attr( - feature = "cargo-clippy", - allow(clippy::identity_op, clippy::double_parens) - )] - fn update_len(&mut self, len: u64) { - let len_bits = [ - (len >> (56 + 5)) as u8, - ((len >> (48 + 5)) & 0xff) as u8, - ((len >> (40 + 5)) & 0xff) as u8, - ((len >> (32 + 5)) & 0xff) as u8, - ((len >> (24 + 5)) & 0xff) as u8, - ((len >> (16 + 5)) & 0xff) as u8, - ((len >> (8 + 5)) & 0xff) as u8, - ((len >> (0 + 5)) & 0xff) as u8, - ((len << 3) & 0xff) as u8, - ]; - - let mut carry = false; - for i in 0..32 { - let mut x = u16::from(self.bit_length[self.bit_length.len() - i - 1]); - - if i < len_bits.len() { - x += u16::from(len_bits[len_bits.len() - i - 1]); - } else if !carry { - break; - } - - if carry { - x += 1; - } - - carry = x > 0xff; - let pos = self.bit_length.len() - i - 1; - self.bit_length[pos] = (x & 0xff) as u8; - } - } +impl FixedOutputCore for WhirlpoolCore { + #[inline] + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + let pos = buffer.get_pos(); + self.update_len(8 * pos as u64); - fn finalize_inner(&mut self) { - // padding - let hash = &mut self.hash; - let pos = self.buffer.position(); - let buf = self - .buffer - .pad_with::() - .expect("we never use input_lazy"); - - if pos + 1 > self.bit_length.len() { - compress(hash, convert(buf)); - buf[..=pos].iter_mut().for_each(|b| *b = 0); + let mut buf = [0u8; 4 * 8]; + for (chunk, v) in buf.chunks_exact_mut(8).zip(self.bit_len.iter()) { + chunk.copy_from_slice(&v.to_be_bytes()); } - buf[32..].copy_from_slice(&self.bit_length); - compress(hash, convert(buf)); + let mut state = self.state; + buffer.digest_pad(0x80, &buf, |block| { + compress(&mut state, convert(from_ref(block))) + }); + + for (chunk, v) in out.chunks_exact_mut(8).zip(state.iter()) { + chunk.copy_from_slice(&v.to_le_bytes()); + } } } -impl BlockInput for Whirlpool { - type BlockSize = BlockSize; +impl WhirlpoolCore { + fn update_len(&mut self, len: u64) { + let mut carry = 0; + adc(&mut self.bit_len[3], len, &mut carry); + adc(&mut self.bit_len[2], 0, &mut carry); + adc(&mut self.bit_len[1], 0, &mut carry); + adc(&mut self.bit_len[0], 0, &mut carry); + } } -impl Update for Whirlpool { - fn update(&mut self, input: impl AsRef<[u8]>) { - let input = input.as_ref(); - self.update_len(input.len() as u64); - let hash = &mut self.hash; - self.buffer - .input_block(input, |b| compress(hash, convert(b))); +impl Default for WhirlpoolCore { + #[inline] + fn default() -> Self { + Self { + bit_len: Default::default(), + state: [0u64; 8], + } } } -impl FixedOutputDirty for Whirlpool { - type OutputSize = U64; - - #[cfg(not(feature = "asm"))] - fn finalize_into_dirty(&mut self, out: &mut GenericArray) { - self.finalize_inner(); - for (chunk, v) in out.chunks_exact_mut(8).zip(self.hash.iter()) { - chunk.copy_from_slice(&v.to_be_bytes()); - } +impl Reset for WhirlpoolCore { + #[inline] + fn reset(&mut self) { + *self = Default::default(); } +} - #[cfg(feature = "asm")] - fn finalize_into_dirty(&mut self, out: &mut GenericArray) { - self.finalize_inner(); - out.copy_from_slice(&self.hash) +impl AlgorithmName for WhirlpoolCore { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Whirlpool") } } -impl Reset for Whirlpool { - fn reset(&mut self) { - self.bit_length = [0u8; 32]; - self.buffer.reset(); - for v in self.hash.iter_mut() { - *v = 0; - } +impl fmt::Debug for WhirlpoolCore { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("WhirlpoolCore { ... }") } } -opaque_debug::implement!(Whirlpool); -digest::impl_write!(Whirlpool); +/// Whirlpool hasher state. +pub type Whirlpool = CoreWrapper; + +#[inline(always)] +fn adc(a: &mut u64, b: u64, carry: &mut u64) { + let ret = (*a as u128) + (b as u128) + (*carry as u128); + *a = ret as u64; + *carry = (ret >> 64) as u64; +} + +const BLOCK_SIZE: usize = ::BlockSize::USIZE; + +#[inline(always)] +fn convert(blocks: &[Block]) -> &[[u8; BLOCK_SIZE]] { + // SAFETY: GenericArray and [u8; 64] have + // exactly the same memory layout + let p = blocks.as_ptr() as *const [u8; BLOCK_SIZE]; + unsafe { core::slice::from_raw_parts(p, blocks.len()) } +} diff --git a/whirlpool/src/utils.rs b/whirlpool/src/utils.rs deleted file mode 100644 index 53312ce7f..000000000 --- a/whirlpool/src/utils.rs +++ /dev/null @@ -1,50 +0,0 @@ -use crate::consts::*; -use core::convert::TryInto; - -pub fn compress(hash: &mut [u64; 8], buffer: &[u8; 64]) { - let mut k = [0u64; 8]; - let mut block = [0u64; 8]; - let mut state = [0u64; 8]; - let mut l = [0u64; 8]; - - for (o, chunk) in block.iter_mut().zip(buffer.chunks_exact(8)) { - *o = u64::from_be_bytes(chunk.try_into().unwrap()); - } - k.copy_from_slice(hash); - - for i in 0..8 { - state[i] = block[i] ^ k[i]; - } - - #[allow(clippy::needless_range_loop)] - for r in 1..=R { - for i in 0..8 { - l[i] = C0[(k[(i) % 8] >> 56) as usize] - ^ C1[((k[(7 + i) % 8] >> 48) & 0xff) as usize] - ^ C2[((k[(6 + i) % 8] >> 40) & 0xff) as usize] - ^ C3[((k[(5 + i) % 8] >> 32) & 0xff) as usize] - ^ C4[((k[(4 + i) % 8] >> 24) & 0xff) as usize] - ^ C5[((k[(3 + i) % 8] >> 16) & 0xff) as usize] - ^ C6[((k[(2 + i) % 8] >> 8) & 0xff) as usize] - ^ C7[((k[(1 + i) % 8]) & 0xff) as usize] - ^ if i == 0 { RC[r] } else { 0 }; - } - k = l; - for i in 0..8 { - l[i] = C0[(state[(i) % 8] >> 56) as usize] - ^ C1[((state[(7 + i) % 8] >> 48) & 0xff) as usize] - ^ C2[((state[(6 + i) % 8] >> 40) & 0xff) as usize] - ^ C3[((state[(5 + i) % 8] >> 32) & 0xff) as usize] - ^ C4[((state[(4 + i) % 8] >> 24) & 0xff) as usize] - ^ C5[((state[(3 + i) % 8] >> 16) & 0xff) as usize] - ^ C6[((state[(2 + i) % 8] >> 8) & 0xff) as usize] - ^ C7[((state[(1 + i) % 8]) & 0xff) as usize] - ^ k[i]; - } - state = l; - } - - for i in 0..8 { - hash[i] ^= state[i] ^ block[i]; - } -} diff --git a/whirlpool/tests/data/whirlpool.blb b/whirlpool/tests/data/whirlpool.blb index a82e549b5..4222b2787 100644 Binary files a/whirlpool/tests/data/whirlpool.blb and b/whirlpool/tests/data/whirlpool.blb differ