From d174ad743c0e8685c03cda484d885686e1661e44 Mon Sep 17 00:00:00 2001 From: Artem Vorotnikov Date: Fri, 9 Jun 2023 07:10:25 +0300 Subject: [PATCH] Skein hash implementation (#483) --- .github/workflows/skein.yml | 61 ++++++++ Cargo.toml | 1 + README.md | 3 + skein/CHANGELOG.md | 11 ++ skein/Cargo.toml | 21 +++ skein/LICENSE-APACHE | 201 +++++++++++++++++++++++++++ skein/LICENSE-MIT | 25 ++++ skein/README.md | 56 ++++++++ skein/benches/skein1024.rs | 14 ++ skein/benches/skein256.rs | 14 ++ skein/benches/skein512.rs | 14 ++ skein/src/lib.rs | 216 +++++++++++++++++++++++++++++ skein/tests/data/skein1024_128.blb | Bin 0 -> 781 bytes skein/tests/data/skein1024_32.blb | Bin 0 -> 185 bytes skein/tests/data/skein1024_64.blb | Bin 0 -> 284 bytes skein/tests/data/skein256_32.blb | Bin 0 -> 385 bytes skein/tests/data/skein256_64.blb | Bin 0 -> 284 bytes skein/tests/data/skein512_32.blb | Bin 0 -> 185 bytes skein/tests/data/skein512_64.blb | Bin 0 -> 680 bytes skein/tests/lib.rs | 13 ++ 20 files changed, 650 insertions(+) create mode 100644 .github/workflows/skein.yml create mode 100644 skein/CHANGELOG.md create mode 100644 skein/Cargo.toml create mode 100644 skein/LICENSE-APACHE create mode 100644 skein/LICENSE-MIT create mode 100644 skein/README.md create mode 100644 skein/benches/skein1024.rs create mode 100644 skein/benches/skein256.rs create mode 100644 skein/benches/skein512.rs create mode 100644 skein/src/lib.rs create mode 100644 skein/tests/data/skein1024_128.blb create mode 100644 skein/tests/data/skein1024_32.blb create mode 100644 skein/tests/data/skein1024_64.blb create mode 100644 skein/tests/data/skein256_32.blb create mode 100644 skein/tests/data/skein256_64.blb create mode 100644 skein/tests/data/skein512_32.blb create mode 100644 skein/tests/data/skein512_64.blb create mode 100644 skein/tests/lib.rs diff --git a/.github/workflows/skein.yml b/.github/workflows/skein.yml new file mode 100644 index 00000000..8f16200c --- /dev/null +++ b/.github/workflows/skein.yml @@ -0,0 +1,61 @@ +name: skein + +on: + pull_request: + paths: + - ".github/workflows/skein.yml" + - "skein/**" + - "Cargo.*" + push: + branches: master + +defaults: + run: + working-directory: skein + +env: + CARGO_INCREMENTAL: 0 + RUSTFLAGS: "-Dwarnings" + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - 1.57.0 # MSRV + - stable + target: + - thumbv7em-none-eabi + - wasm32-unknown-unknown + steps: + - uses: actions/checkout@v3 + - uses: RustCrypto/actions/cargo-cache@master + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + targets: ${{ matrix.target }} + - run: cargo build --no-default-features --target ${{ matrix.target }} + + minimal-versions: + uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master + with: + working-directory: ${{ github.workflow }} + + test: + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - 1.57.0 # MSRV + - stable + steps: + - uses: actions/checkout@v3 + - uses: RustCrypto/actions/cargo-cache@master + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + - run: cargo check --all-features + - run: cargo test --no-default-features + - run: cargo test + - run: cargo test --all-features diff --git a/Cargo.toml b/Cargo.toml index 7f544e28..85c713c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ members = [ exclude = [ "ascon-hash", "belt-hash", + "skein", ] [profile.dev] diff --git a/README.md b/README.md index 539e77f3..887353d1 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ Additionally all crates do not require the standard library (i.e. `no_std` capab | [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) | ![MSRV 1.41][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) | ![MSRV 1.41][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) | ![MSRV 1.41][msrv-1.41] | :green_heart: | +| [Skein] | [`skein`] | [![crates.io](https://img.shields.io/crates/v/skein.svg)](https://crates.io/crates/skein) | [![Documentation](https://docs.rs/skein/badge.svg)](https://docs.rs/skein) | ![MSRV 1.57][msrv-1.57] | :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) | ![MSRV 1.41][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) | ![MSRV 1.41][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) | ![MSRV 1.41][msrv-1.41] | :green_heart: | @@ -252,6 +253,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [`sha2`]: ./sha2 [`sha3`]: ./sha3 [`shabal`]: ./shabal +[`skein`]: ./skein [`sm3`]: ./sm3 [`streebog`]: ./streebog [`tiger`]: ./tiger @@ -291,6 +293,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [SHA-2]: https://en.wikipedia.org/wiki/SHA-2 [SHA-3]: https://en.wikipedia.org/wiki/SHA-3 [SHABAL]: https://www.cs.rit.edu/~ark/20090927/Round2Candidates/Shabal.pdf +[Skein]: https://schneier.com/academic/skein [SM3]: https://en.wikipedia.org/wiki/SM3_(hash_function) [Streebog]: https://en.wikipedia.org/wiki/Streebog [Whirlpool]: https://en.wikipedia.org/wiki/Whirlpool_(cryptography) diff --git a/skein/CHANGELOG.md b/skein/CHANGELOG.md new file mode 100644 index 00000000..54f3b9ef --- /dev/null +++ b/skein/CHANGELOG.md @@ -0,0 +1,11 @@ +# 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 (2023-06-09) +- Initial release ([#483]) + +[#483]: https://github.com/RustCrypto/hashes/pull/483 diff --git a/skein/Cargo.toml b/skein/Cargo.toml new file mode 100644 index 00000000..5f1d5987 --- /dev/null +++ b/skein/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "skein" +version = "0.1.0" +description = "Skein hash functions" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +edition = "2021" +rust-version = "1.57" +readme = "README.md" +documentation = "https://docs.rs/skein" +repository = "https://github.com/RustCrypto/hashes" +keywords = ["crypto", "skein", "hash", "digest"] +categories = ["cryptography", "no-std"] + +[dependencies] +digest = "0.10" +threefish = { version = "0.5.2", default-features = false } + +[dev-dependencies] +digest = { version = "0.10", features = ["dev"] } +hex-literal = "0.4" diff --git a/skein/LICENSE-APACHE b/skein/LICENSE-APACHE new file mode 100644 index 00000000..1eb32153 --- /dev/null +++ b/skein/LICENSE-APACHE @@ -0,0 +1,201 @@ + 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 2019 The CryptoCorrosion Contributors + +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/skein/LICENSE-MIT b/skein/LICENSE-MIT new file mode 100644 index 00000000..50c61807 --- /dev/null +++ b/skein/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2023 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/skein/README.md b/skein/README.md new file mode 100644 index 00000000..c1135eee --- /dev/null +++ b/skein/README.md @@ -0,0 +1,56 @@ +# RustCrypto: Skein + +[![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 [Skein] family of cryptographic hash algorithms. + +[Documentation][docs-link] + +## Minimum Supported Rust Version + +Rust **1.57** 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/skein.svg +[crate-link]: https://crates.io/crates/skein +[docs-image]: https://docs.rs/skein/badge.svg +[docs-link]: https://docs.rs/skein/ +[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.57+-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/skein/badge.svg?branch=master +[build-link]: https://github.com/RustCrypto/hashes/actions?query=workflow%3Askein + +[//]: # (general links) + +[Skein]: https://schneier.com/academic/skein diff --git a/skein/benches/skein1024.rs b/skein/benches/skein1024.rs new file mode 100644 index 00000000..2101cdb3 --- /dev/null +++ b/skein/benches/skein1024.rs @@ -0,0 +1,14 @@ +#![feature(test)] +extern crate test; + +use digest::{bench_update, generic_array::typenum::U128}; +use skein::Skein1024; +use test::Bencher; + +bench_update!( + Skein1024::::default(); + skein_1024_10 10; + skein_1024_100 100; + skein_1024_1000 1000; + skein_1024_10000 10000; +); diff --git a/skein/benches/skein256.rs b/skein/benches/skein256.rs new file mode 100644 index 00000000..c2646fc7 --- /dev/null +++ b/skein/benches/skein256.rs @@ -0,0 +1,14 @@ +#![feature(test)] +extern crate test; + +use digest::{bench_update, generic_array::typenum::U32}; +use skein::Skein256; +use test::Bencher; + +bench_update!( + Skein256::::default(); + skein_256_10 10; + skein_256_100 100; + skein_256_1000 1000; + skein_256_10000 10000; +); diff --git a/skein/benches/skein512.rs b/skein/benches/skein512.rs new file mode 100644 index 00000000..727db698 --- /dev/null +++ b/skein/benches/skein512.rs @@ -0,0 +1,14 @@ +#![feature(test)] +extern crate test; + +use digest::{bench_update, generic_array::typenum::U64}; +use skein::Skein512; +use test::Bencher; + +bench_update!( + Skein512::::default(); + skein_512_10 10; + skein_512_100 100; + skein_512_1000 1000; + skein_512_10000 10000; +); diff --git a/skein/src/lib.rs b/skein/src/lib.rs new file mode 100644 index 00000000..6f6bcf76 --- /dev/null +++ b/skein/src/lib.rs @@ -0,0 +1,216 @@ +//! Implementation of the [Skein] family of cryptographic hash algorithms. +//! +//! There are 3 standard versions of the Skein hash function: +//! +//! * [`Skein256`] +//! * [`Skein512`] +//! * [`Skein1024`] +//! +//! Output size of the Skein hash functions is arbitrary, so it has to be +//! fixed using additional type parameter +//! +//! # Examples +//! Hash functionality is usually accessed via the [`Digest`] trait: +//! +//! ``` +//! use hex_literal::hex; +//! use skein::{Digest, Skein512, consts::U32}; +//! +//! // Create a Skein-512-256 hasher object +//! let mut hasher = Skein512::::new(); +//! +//! // Write input message +//! hasher.update(b"The quick brown fox "); +//! hasher.update(b"jumps over the lazy dog"); +//! +//! // Read hash digest +//! let result = hasher.finalize(); +//! +//! let expected = hex!("b3250457e05d3060b1a4bbc1428bc75a3f525ca389aeab96cfa34638d96e492a"); +//! assert_eq!(result[..], expected[..]); +//! ``` +//! Also see [RustCrypto/hashes] readme. +//! +//! [Skein]: https://schneier.com/academic/skein +//! [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" +)] +#![warn(missing_docs, rust_2018_idioms)] +#![deny(unsafe_code)] + +pub use digest::{self, consts, Digest}; + +use core::{fmt, marker::PhantomData}; +use digest::{ + block_buffer::Lazy, + consts::{U128, U32, U64}, + core_api::{ + AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore, + OutputSizeUser, Reset, UpdateCore, + }, + generic_array::{typenum::Unsigned, ArrayLength, GenericArray}, + HashMarker, Output, +}; +use threefish::{Threefish1024, Threefish256, Threefish512}; + +const VERSION: u64 = 1; +const ID_STRING_LE: u64 = 0x3341_4853; +const SCHEMA_VER: u64 = (VERSION << 32) | ID_STRING_LE; +const CFG_TREE_INFO_SEQUENTIAL: u64 = 0; +const T1_FLAG_FIRST: u64 = 1 << 62; +const T1_FLAG_FINAL: u64 = 1 << 63; +const T1_BLK_TYPE_CFG: u64 = 4 << 56; +const T1_BLK_TYPE_MSG: u64 = 48 << 56; +const T1_BLK_TYPE_OUT: u64 = 63 << 56; +const CFG_STR_LEN: usize = 4 * 8; + +macro_rules! define_hasher { + ( + $name:ident, $full_name:ident, $threefish:ident, + $state_bytes:ty, $alg_name:expr + ) => { + #[doc = $alg_name] + #[doc = " core hasher state"] + #[derive(Clone)] + pub struct $name + 'static> { + t: [u64; 2], + x: [u64; <$state_bytes>::USIZE / 8], + _pd: PhantomData, + } + + impl + 'static> $name { + fn blank_state(t1: u64, x: [u64; <$state_bytes>::USIZE / 8]) -> Self { + Self { + t: [0, t1], + x, + _pd: PhantomData, + } + } + + fn process_block( + &mut self, + block: &GenericArray, + byte_count_add: usize, + ) { + const STATE_WORDS: usize = <$state_bytes>::USIZE / 8; + + self.t[0] += byte_count_add as u64; + let cipher = $threefish::new_with_tweak_u64(&self.x.into(), &self.t); + + let mut x = [0u64; STATE_WORDS]; + for (src, dst) in block.chunks_exact(8).zip(x.iter_mut()) { + *dst = u64::from_le_bytes(src.try_into().unwrap()); + } + let t = x; + + cipher.encrypt_block_u64(&mut x); + + for i in 0..STATE_WORDS { + self.x[i] = t[i] ^ x[i]; + } + self.t[1] &= !T1_FLAG_FIRST; + } + } + + impl HashMarker for $name where N: ArrayLength + 'static {} + + impl + 'static> BlockSizeUser for $name { + type BlockSize = $state_bytes; + } + + impl + 'static> BufferKindUser for $name { + type BufferKind = Lazy; + } + + impl + 'static> OutputSizeUser for $name { + type OutputSize = N; + } + + impl + 'static> UpdateCore for $name { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + for block in blocks { + self.process_block(block, block.len()) + } + } + } + + impl + 'static> FixedOutputCore for $name { + #[inline] + fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + self.t[1] |= T1_FLAG_FINAL; + let pos = buffer.get_pos(); + let final_block = buffer.pad_with_zeros(); + self.process_block(final_block, pos); + + // run Threefish in "counter mode" to generate output + let flag = T1_FLAG_FIRST | T1_BLK_TYPE_OUT | T1_FLAG_FINAL; + let mut block = GenericArray::::default(); + for (i, chunk) in out.chunks_mut(<$state_bytes>::USIZE).enumerate() { + let mut ctr = Self::blank_state(flag, self.x); + + block[..8].copy_from_slice(&(i as u64).to_le_bytes()); + Self::process_block(&mut ctr, &block, 8); + + for (src, dst) in ctr.x.iter().zip(chunk.chunks_exact_mut(8)) { + dst.copy_from_slice(&src.to_le_bytes()); + } + } + } + } + + impl + 'static> Default for $name { + fn default() -> Self { + // build and process config block + let mut state = Self::blank_state( + T1_FLAG_FIRST | T1_BLK_TYPE_CFG | T1_FLAG_FINAL, + Default::default(), + ); + + let mut cfg = GenericArray::::default(); + cfg[..8].copy_from_slice(&SCHEMA_VER.to_le_bytes()); + cfg[8..16].copy_from_slice(&(N::to_u64() * 8).to_le_bytes()); + cfg[16..24].copy_from_slice(&CFG_TREE_INFO_SEQUENTIAL.to_le_bytes()); + + state.process_block(&cfg, CFG_STR_LEN); + + // The chaining vars ctx->X are now initialized for the given hashBitLen. + // Set up to process the data message portion of the hash (default) + state.t = [0, T1_FLAG_FIRST | T1_BLK_TYPE_MSG]; + state + } + } + + impl + 'static> Reset for $name { + #[inline] + fn reset(&mut self) { + *self = Default::default(); + } + } + + impl + 'static> AlgorithmName for $name { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(stringify!($full_name)) + } + } + + impl + 'static> fmt::Debug for $name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + write!(f, "{}<{}> {{ .. }}", stringify!($name), N::USIZE) + } + } + + #[doc = $alg_name] + #[doc = " hasher state"] + pub type $full_name = CoreWrapper<$name>; + }; +} + +define_hasher!(Skein256Core, Skein256, Threefish256, U32, "Skein-256"); +define_hasher!(Skein512Core, Skein512, Threefish512, U64, "Skein-512"); +#[rustfmt::skip] +define_hasher!(Skein1024Core, Skein1024, Threefish1024, U128, "Skein-1024"); diff --git a/skein/tests/data/skein1024_128.blb b/skein/tests/data/skein1024_128.blb new file mode 100644 index 0000000000000000000000000000000000000000..6e844a97475cb89645e690422142082d803e5068 GIT binary patch literal 781 zcmZQz`rpX#Ooz2WZ-J-^``H^6^|$7k7TCT>TJrm#mOnxzC)~{OjXh6{XcN zylVEFeyrd8ecA^P2Ij_K>3oJ8fr)$g|9ihzY1{bvtaEnm@@7}(7{p#h5=g*!#dHm?%gZuaH-no72=8fyuu3ou(>Eea+=gyuved^?i z(;JWy=vu(<;#{XS-fcBg8B32&Y3-H z=8WmnrcRkWY2t+bzTTehuFj73w$_&BrpAUw26;QCBl$bH?9b}{-cuuP!LWrV;gG4< z*FcGR`<-oUTYvtSV19N}!PBtvZPoKX&*qpmE?x9P*N&%3GqmKw*;>UK4`2Oc;j6RC zC0<>qW!F695qSOiB~R%Ix*ij!JllRb^ETJ^RRZ~Z4;IgIdVkbk;-+~S2WRU~_Hh51 zamN-H1~08>9`G=zudA)8uBxmkFDor6E-Ea@&&$op&dSV4PfJZnPD)IOkBg0oj*5&3 z4+{+m4hjtL_w)7f_VV;_cXM@dc5-yEx3jgewz9M^H#0RcHZnBO*VEO}*3#5aS5s9{ zR#H@umy?x|mXeeZ7ZVi`77`TT=i}w!=HldFXJchyW@2P$WN6U}J~>Bd!}*5unV!;5 zAAJvueNk+kx6(=XFVGEJe>wf%yz)qoVtM&g4v%wZxAdp*H~yZq@7s_5s@8+w&x*L6 z6qDil*RQ(H#oys_21DcFs3rC({8xY3*f4XSVOzb1@xqKfCtF_MFj5zqB*(CE7yGpf U@@f+b0#xHZop|J5m=m-V0K-0?YybcN literal 0 HcmV?d00001 diff --git a/skein/tests/data/skein1024_32.blb b/skein/tests/data/skein1024_32.blb new file mode 100644 index 0000000000000000000000000000000000000000..621b9c7cbef104cd4d8ea284a06aa63bab146d8b GIT binary patch literal 185 zcmV;q07m}+06-2>1L}Ja(c>}?3jtoZQn)4=ty!3Wyzy4;E_KD5@%$pbWuvQ2->^=d!TuyIUvm6_naz5l*MI=9{XUzF`D*b# zvEZeg{~`u{=e-VXcUrRSOv*3GZx nl(%L;>ne^a`3xxWPm(N}wb=)~Tlt32nxCz{B{bak1l<*EJy2XX literal 0 HcmV?d00001 diff --git a/skein/tests/data/skein1024_64.blb b/skein/tests/data/skein1024_64.blb new file mode 100644 index 0000000000000000000000000000000000000000..bce87fdd659c010c498a3f47fee6cb2e0519f4a6 GIT binary patch literal 284 zcmV+%0ptDv0Du7Els>S$4*I=GP&#()_s`DuL2ksenF3xzx z7qEPh%Mq7HG0L|L4)UK|_^Du7a=pCCv${(T|Ns5{^ZVD&AK$-y{qp(K#}Dt{y?yig z)yo&ppFMr@_|d}$4!!(K-j~;3kGy|{#VhSTBbtj$g{9&I|U1S}*-=VvKfshgR z@7=v~`_|1H*RNf@a{1E53+K?l`YYP1! zy$XG-_>7N26(jXATmS+%j5+Ky>q(X(x9`FPeLMxAbbs=+afO22qcG$!F)kN7eD>O$N z#-cHgbD?*t3N9o^UI-UDJyU9=a!esOv iOsVuF>Bd(T%U40RO6O=$4?JxV)>404&Q64E$$>cw(~O1y literal 0 HcmV?d00001 diff --git a/skein/tests/data/skein512_32.blb b/skein/tests/data/skein512_32.blb new file mode 100644 index 0000000000000000000000000000000000000000..8db92a590d99f7d50b56c8c8bb1da651e00cb487 GIT binary patch literal 185 zcmV;q07m}+06;m+#8pa*F@-yw=b`>%iX_bDvszX1Ll6n!hk!F(CLtn}O1zwGyUha; zFO5*0G35%9K;8-Ot_l$+1@THQoQZ08zZbkl9zN>zLs1_m;ggui(46_ux+UT(a5t@)Dm{0p+a$e*fYzL1*oZ~3Cj z#k_lW@W{7@>HaxTVC=W#;?3teyQ-8Nx{gdX{yrnU?r@No!7Oi)YYhxNJIvFqB)UNV%lGnz{A!Jm(+fQ{0jcT4lsWb{*bdp3U{1`TgVbY3&;i-Fg{f z;;qd5JMrjZTgCznUy=SwnddIm`}hnL8yL!228P1zd!GGE z2~w(_^EN?5WnT2pm8Cvb*Cfsyd9dnXwqeeRQ<=SO&g^gP8n(R`Eojs_s;+y4bL#@3 z`&!`>nLaxtRy8pE|M&OL?_WQEeE;_K%jZuYKfHhU_RZ^8FJC-=_Vmf)M-Ly|zjyb} z?OQi*T)%ep%H>NJFPuMj_RQ&1Cr=zdcJ#>MLkABuFu1l^FW$%F`$zqGtZB=%FKcEM zX9dJg7T%(*AGdb-{Dbw$ZE{npe#^3EEu0x1b@|81#b?ADwm$vkvyPQ-#*DJ0=thd& zuz%m)J-c`9+_8Pz)-9ViZQQVa-P$#)SFK#JeA&_^ix(|iFn`|MIkRWYoH2dc)G3oE zO`Oo**W1(G)!EVB*4onC)Y#C#F!9V%fkVkh?p_cG<}zkC=1gic{LE2OCw+R=geQTg ocIpLoa8!MfXfIxDWMG$;zI>5DYkrBMB?Cj@m%i>rOV@4(0Ap^12LJ#7 literal 0 HcmV?d00001 diff --git a/skein/tests/lib.rs b/skein/tests/lib.rs new file mode 100644 index 00000000..54360d76 --- /dev/null +++ b/skein/tests/lib.rs @@ -0,0 +1,13 @@ +use skein::{ + consts::{U128, U32, U64}, + digest::{dev::fixed_test, new_test}, + Skein1024, Skein256, Skein512, +}; + +new_test!(skein256_32, "skein256_32", Skein256, fixed_test); +new_test!(skein256_64, "skein256_64", Skein256, fixed_test); +new_test!(skein512_32, "skein512_32", Skein512, fixed_test); +new_test!(skein512_64, "skein512_64", Skein512, fixed_test); +new_test!(skein1024_32, "skein1024_32", Skein1024, fixed_test); +new_test!(skein1024_64, "skein1024_64", Skein1024, fixed_test); +new_test!(skein1024_128, "skein1024_128", Skein1024, fixed_test);