From 347e752e37eacb5017463f26d13edb0c1ec8b873 Mon Sep 17 00:00:00 2001 From: cscherr Date: Tue, 22 Jul 2025 13:26:57 +0200 Subject: [PATCH] refactor(alg): smaller alg changes for testing and qol --- Cargo.lock | 20 ++++++- crates/algorithms/Cargo.toml | 12 +++++ crates/algorithms/src/bin/crc32sum.rs | 0 crates/algorithms/src/bin/sha256sum.rs | 27 ++++++++++ crates/algorithms/src/ffi/mod.rs | 2 - crates/algorithms/src/hash/ffi/sha2.rs | 20 +------ crates/algorithms/src/hash/mod.rs | 73 ++++++++++++++++++++++++++ crates/algorithms/src/hash/sha2.rs | 52 ++++-------------- 8 files changed, 141 insertions(+), 65 deletions(-) create mode 100644 crates/algorithms/src/bin/crc32sum.rs create mode 100644 crates/algorithms/src/bin/sha256sum.rs diff --git a/Cargo.lock b/Cargo.lock index c5aaaf0..4da5266 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,7 @@ version = "0.1.0" dependencies = [ "assert_hex", "criterion", + "getopts", "iai", "pretty_assertions", ] @@ -115,7 +116,7 @@ checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "bitflags", "textwrap", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -321,6 +322,15 @@ dependencies = [ "num", ] +[[package]] +name = "getopts" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cba6ae63eb948698e300f645f87c70f76630d505f23b8907cf1e193ee85048c1" +dependencies = [ + "unicode-width 0.2.1", +] + [[package]] name = "half" version = "1.8.3" @@ -779,7 +789,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -824,6 +834,12 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "unicode-width" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" + [[package]] name = "vcell" version = "0.1.3" diff --git a/crates/algorithms/Cargo.toml b/crates/algorithms/Cargo.toml index 1267ee2..db2cdd0 100755 --- a/crates/algorithms/Cargo.toml +++ b/crates/algorithms/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2024" [dependencies] +getopts = { version = "0.2.23", optional = true } [dev-dependencies] assert_hex = "0.4.1" @@ -23,3 +24,14 @@ harness = false default = [] std = [] show_internals = ["std"] +getopts = ["dep:getopts"] + +[[bin]] +path = "src/bin/crc32sum.rs" +name = "crc32sum" +required-features = ["std"] + +[[bin]] +path = "src/bin/sha256sum.rs" +name = "sha256sum" +required-features = ["std"] diff --git a/crates/algorithms/src/bin/crc32sum.rs b/crates/algorithms/src/bin/crc32sum.rs new file mode 100644 index 0000000..e69de29 diff --git a/crates/algorithms/src/bin/sha256sum.rs b/crates/algorithms/src/bin/sha256sum.rs new file mode 100644 index 0000000..68f6298 --- /dev/null +++ b/crates/algorithms/src/bin/sha256sum.rs @@ -0,0 +1,27 @@ +use algorithms::hash::format_digest; + +fn main() { + let args: Vec = std::env::args().collect(); + let use_ffi = args.contains(&"-c".to_string()); + if args.len() < 2 { + usage(&args[0], 1) + } + let input = &args[1]; + println!("{:x?}", input.as_bytes()); + let raw_in = input.as_bytes(); + let hash = if use_ffi { + algorithms::hash::ffi::sha2_256_oneshot(raw_in).expect("could not hash your input data") + } else { + algorithms::hash::sha2_256_oneshot(raw_in).expect("could not hash your input data") + }; + println!("{}", format_digest(&bytes(&hash))); +} + +fn bytes(data: &[u32]) -> Vec { + data.iter().flat_map(|x| x.to_ne_bytes()).collect() +} + +fn usage(call: &str, code: i32) -> ! { + println!("USAGE: {call} INPUT [-c]"); + std::process::exit(code) +} diff --git a/crates/algorithms/src/ffi/mod.rs b/crates/algorithms/src/ffi/mod.rs index ccaa155..3625c20 100755 --- a/crates/algorithms/src/ffi/mod.rs +++ b/crates/algorithms/src/ffi/mod.rs @@ -1,5 +1,3 @@ -use core::ffi::c_void; - unsafe extern "C" { fn algorithms_c_is_loaded() -> i32; } diff --git a/crates/algorithms/src/hash/ffi/sha2.rs b/crates/algorithms/src/hash/ffi/sha2.rs index a652ddd..35de1ce 100644 --- a/crates/algorithms/src/hash/ffi/sha2.rs +++ b/crates/algorithms/src/hash/ffi/sha2.rs @@ -105,26 +105,10 @@ pub(crate) fn to_res(if_ok: T, res: SHA2Outcome) -> Result { mod test { use crate::hash::Digest256; use crate::hash::ffi::sha2_256_oneshot; - - const TEST_VALUES: &[(&str, Digest256)] = &[ - ( - "AAAA", - [ - 0x63c1dd95, 0x1ffedf6f, 0x7fd968ad, 0x4efa39b8, 0xed584f16, 0x2f46e715, 0x114ee184, - 0xf8de9201, - ], - ), - ( - "BAAA", - [ - 0x49e3cd45, 0x27c96cdc, 0x010160ff, 0x08520e0c, 0xb63c6ef8, 0xc4e7d486, 0x08995343, - 0x7f83a159, - ], - ), - ]; + use crate::hash::test::TEST_VALUES; #[test] - fn test_check() { + fn test_sha2_ffi_check() { for (input, expected_output) in TEST_VALUES.iter().copied() { assert_eq!(sha2_256_oneshot(input.as_bytes()), Ok(expected_output)) } diff --git a/crates/algorithms/src/hash/mod.rs b/crates/algorithms/src/hash/mod.rs index 349a7bb..4c8de95 100644 --- a/crates/algorithms/src/hash/mod.rs +++ b/crates/algorithms/src/hash/mod.rs @@ -4,3 +4,76 @@ mod sha2; pub use sha2::*; pub const HASH_EXAMPLE_DATA: &[u8] = b"lalilolela"; + +#[cfg(feature = "std")] +pub fn format_digest(digest: &[u8]) -> String { + digest + .iter() + .map(|b| format!("{b:02x}")) + .collect::() +} + +#[cfg(test)] +pub(crate) mod test { + use super::*; + use assert_hex::*; + use pretty_assertions::{assert_eq, assert_ne}; + + #[macro_export] + macro_rules! assert_eq_bin { + ($left:expr, $right:expr $(,)?) => ({ + match (&$left, &$right) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + panic!(r#"assertion `left == right` failed + left: {:b} + right: {:b}"#, &*left_val, &*right_val) + } + } + } + }); + ($left:expr, $right:expr, $($arg:tt)+) => ({ + match (&($left), &($right)) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + panic!(r#"assertion `left == right` failed: {} + left: {:b} + right: {:b}"#, format_args!($($arg)+), &*left_val, &*right_val) + } + } + } + }); +} + + pub(crate) const TEST_VALUES: &[(&str, Digest256)] = &[ + ( + "AAAA", + [ + 0x63c1dd95, 0x1ffedf6f, 0x7fd968ad, 0x4efa39b8, 0xed584f16, 0x2f46e715, 0x114ee184, + 0xf8de9201, + ], + ), + ( + "BAAA", + [ + 0x49e3cd45, 0x27c96cdc, 0x010160ff, 0x08520e0c, 0xb63c6ef8, 0xc4e7d486, 0x08995343, + 0x7f83a159, + ], + ), + ]; + + #[test] + fn test_sha2_ffi_same_as_native() { + let mut dig_native; + let mut dig_ffi; + for (input, expected_output) in TEST_VALUES.iter().copied() { + dig_native = sha2_256_oneshot(input.as_bytes()).unwrap(); + dig_ffi = ffi::sha2_256_oneshot(input.as_bytes()).unwrap(); + assert_eq_hex!( + dig_native, + dig_ffi, + "ffi does not return the same result as native" + ) + } + } +} diff --git a/crates/algorithms/src/hash/sha2.rs b/crates/algorithms/src/hash/sha2.rs index b1aa991..af5044d 100644 --- a/crates/algorithms/src/hash/sha2.rs +++ b/crates/algorithms/src/hash/sha2.rs @@ -53,6 +53,7 @@ impl Sha2_256Context { } } + #[inline] pub fn clear(&mut self) { *self = Self::new(); } @@ -206,6 +207,7 @@ impl Sha2_256Context { Ok(()) } + #[inline] fn finalize(&mut self) { self.pad_block(); } @@ -260,20 +262,24 @@ impl Sha2_256Context { } /// This is a different function for W + #[inline] fn sha256_sigma0_w(word: u32) -> u32 { Self::sha256_rotr(7, word) ^ Self::sha256_rotr(18, word) ^ Self::sha256_shr(3, word) } /// This is a different function for W + #[inline] fn sha256_sigma1_w(word: u32) -> u32 { Self::sha256_rotr(17, word) ^ Self::sha256_rotr(19, word) ^ Self::sha256_shr(10, word) } // NOTE: these do not use shift right for the last internal variable! + #[inline] fn sha256_sigma0(word: u32) -> u32 { Self::sha256_rotr(2, word) ^ Self::sha256_rotr(13, word) ^ Self::sha256_rotr(22, word) } + #[inline] fn sha256_sigma1(word: u32) -> u32 { Self::sha256_rotr(6, word) ^ Self::sha256_rotr(11, word) ^ Self::sha256_rotr(25, word) } @@ -285,7 +291,7 @@ impl Sha2_256Context { #[inline] fn sha_maj(x: u32, y: u32, z: u32) -> u32 { - (x & (y | z)) | (y & z) + (x & y) ^ (x & z) ^ (y & z) } } @@ -347,51 +353,11 @@ use debug::*; #[cfg(test)] mod test { use super::*; + use crate::assert_eq_bin; + use crate::hash::test::TEST_VALUES; use assert_hex::*; use pretty_assertions::{assert_eq, assert_ne}; - macro_rules! assert_eq_bin { - ($left:expr, $right:expr $(,)?) => ({ - match (&$left, &$right) { - (left_val, right_val) => { - if !(*left_val == *right_val) { - panic!(r#"assertion `left == right` failed - left: {:b} - right: {:b}"#, &*left_val, &*right_val) - } - } - } - }); - ($left:expr, $right:expr, $($arg:tt)+) => ({ - match (&($left), &($right)) { - (left_val, right_val) => { - if !(*left_val == *right_val) { - panic!(r#"assertion `left == right` failed: {} - left: {:b} - right: {:b}"#, format_args!($($arg)+), &*left_val, &*right_val) - } - } - } - }); -} - - const TEST_VALUES: &[(&str, Digest256)] = &[ - ( - "AAAA", - [ - 0x63c1dd95, 0x1ffedf6f, 0x7fd968ad, 0x4efa39b8, 0xed584f16, 0x2f46e715, 0x114ee184, - 0xf8de9201, - ], - ), - ( - "BAAA", - [ - 0x49e3cd45, 0x27c96cdc, 0x010160ff, 0x08520e0c, 0xb63c6ef8, 0xc4e7d486, 0x08995343, - 0x7f83a159, - ], - ), - ]; - #[test] fn test_sha256_check() { let mut dig;