diff --git a/.github/workflows/skein.yml b/.github/workflows/skein.yml new file mode 100644 index 000000000..8f16200cf --- /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 7f544e284..85c713c97 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 539e77f39..887353d1e 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 000000000..54f3b9ef0 --- /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 000000000..5f1d59871 --- /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 000000000..1eb321535 --- /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 000000000..50c61807c --- /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 000000000..c1135eeec --- /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 000000000..2101cdb34 --- /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 000000000..c2646fc79 --- /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 000000000..727db6989 --- /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 000000000..6f6bcf76e --- /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 000000000..6e844a974 Binary files /dev/null and b/skein/tests/data/skein1024_128.blb differ diff --git a/skein/tests/data/skein1024_32.blb b/skein/tests/data/skein1024_32.blb new file mode 100644 index 000000000..621b9c7cb Binary files /dev/null and b/skein/tests/data/skein1024_32.blb differ diff --git a/skein/tests/data/skein1024_64.blb b/skein/tests/data/skein1024_64.blb new file mode 100644 index 000000000..bce87fdd6 Binary files /dev/null and b/skein/tests/data/skein1024_64.blb differ diff --git a/skein/tests/data/skein256_32.blb b/skein/tests/data/skein256_32.blb new file mode 100644 index 000000000..3e9aa1f31 Binary files /dev/null and b/skein/tests/data/skein256_32.blb differ diff --git a/skein/tests/data/skein256_64.blb b/skein/tests/data/skein256_64.blb new file mode 100644 index 000000000..4842a042e Binary files /dev/null and b/skein/tests/data/skein256_64.blb differ diff --git a/skein/tests/data/skein512_32.blb b/skein/tests/data/skein512_32.blb new file mode 100644 index 000000000..8db92a590 Binary files /dev/null and b/skein/tests/data/skein512_32.blb differ diff --git a/skein/tests/data/skein512_64.blb b/skein/tests/data/skein512_64.blb new file mode 100644 index 000000000..e071f313c Binary files /dev/null and b/skein/tests/data/skein512_64.blb differ diff --git a/skein/tests/lib.rs b/skein/tests/lib.rs new file mode 100644 index 000000000..54360d763 --- /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);