From 41841cdcd64a727f9ee8e64e6cd42638bdebb06e Mon Sep 17 00:00:00 2001 From: David Senk Date: Sun, 17 Aug 2025 13:07:43 -0400 Subject: [PATCH] add blake2 256/512 impls --- src/args.rs | 3 +++ src/hashes.rs | 10 ++++++++ src/hashes/blake256.rs | 29 +++++++++++++++++++---- src/hashes/blake512.rs | 52 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 src/hashes/blake512.rs diff --git a/src/args.rs b/src/args.rs index 877418a..7d9dfdc 100644 --- a/src/args.rs +++ b/src/args.rs @@ -25,6 +25,9 @@ pub struct Args { /// Blake2b256 #[arg(long)] pub blake256: bool, + /// Blake2b512 + #[arg(long)] + pub blake512: bool, /// Blake3 #[arg(long)] pub blake3: bool, diff --git a/src/hashes.rs b/src/hashes.rs index 5b21364..122ee64 100644 --- a/src/hashes.rs +++ b/src/hashes.rs @@ -1,5 +1,7 @@ mod blake256; + mod blake3; +mod blake512; mod crc32; mod md5; mod null_hash; @@ -11,6 +13,8 @@ use crate::Args; use std::sync::Arc; +type BITS512 = [u8; 64]; + type BITS256 = [u8; 32]; type BITS160 = [u8; 20]; @@ -30,12 +34,17 @@ fn arc_u8_empty() -> ArcU8 { arc_u8_sized!(0) } +fn bits512_default() -> BITS512 { + [0; 64] +} + #[derive(Debug, PartialEq)] pub enum HashReturn { CRC32(BITS32), SHA256(BITS256), SHA3_256(BITS256), BLAKE256(BITS256), + BLAKE512(BITS512), BLAKE3(BITS256), SHA1(BITS160), MD5(BITS128), @@ -49,6 +58,7 @@ impl HashReturn { HashReturn::SHA256(inner) => Arc::new(inner), HashReturn::SHA3_256(inner) => Arc::new(inner), HashReturn::BLAKE256(inner) => Arc::new(inner), + HashReturn::BLAKE512(inner) => Arc::new(inner), HashReturn::BLAKE3(inner) => Arc::new(inner), HashReturn::SHA1(inner) => Arc::new(inner), HashReturn::MD5(inner) => Arc::new(inner), diff --git a/src/hashes/blake256.rs b/src/hashes/blake256.rs index 1e95d09..fd23c9d 100644 --- a/src/hashes/blake256.rs +++ b/src/hashes/blake256.rs @@ -1,20 +1,30 @@ use super::*; +use ::blake2::Blake2bVarCore; +use ::blake2::digest::{Update, VariableOutput}; +use blake2::digest::core_api::RtVariableCoreWrapper; pub struct BLAKE256 { hash: BITS256, + hasher: RtVariableCoreWrapper, } impl Hasher for BLAKE256 { fn new() -> Self { - BLAKE256 { hash: [0; 32] } + BLAKE256 { + hash: [0; 32], + hasher: ::blake2::Blake2bVar::new(32).unwrap(), + } } fn digest(&mut self, bytes: impl AsRef<[u8]>) { - todo!() + self.hasher.update(bytes.as_ref()) } fn complete(self) -> HashReturn { - todo!() + let res = self.hasher.finalize_boxed(); + let mut ret = BITS256::default(); + ret.copy_from_slice(&res); + HashReturn::BLAKE256(ret) } } @@ -24,6 +34,17 @@ mod test { #[test] fn test_blake256_hash() { - todo!(); + let input = "HelloWorld"; + let expected_output = "27159ce7d992c98fb04d5e9a59e43e75f77882b676fc6b2ccb8e952c2373da3e"; + + let mut blake2 = BLAKE256::new(); + + blake2.digest(input); + + let result = blake2.complete().into_bytes(); + + let hash_out = crate::hex_table::u8_array_to_lower_hex_string(&result).unwrap(); + + assert_eq!(hash_out, expected_output); } } diff --git a/src/hashes/blake512.rs b/src/hashes/blake512.rs new file mode 100644 index 0000000..1cc681b --- /dev/null +++ b/src/hashes/blake512.rs @@ -0,0 +1,52 @@ +use super::*; +use ::blake2::Blake2bVarCore; +use ::blake2::digest::{Update, VariableOutput}; +use blake2::digest::core_api::RtVariableCoreWrapper; + +pub struct BLAKE512 { + hash: BITS512, + hasher: RtVariableCoreWrapper, +} + +impl Hasher for BLAKE512 { + fn new() -> Self { + BLAKE512 { + hash: [0; 64], + // Variable size was done instead of using Blake2b512 type alias as the concrete type + // that would need to be defined in the struct BLAKE512 is silly + hasher: ::blake2::Blake2bVar::new(64).unwrap(), + } + } + + fn digest(&mut self, bytes: impl AsRef<[u8]>) { + self.hasher.update(bytes.as_ref()) + } + + fn complete(self) -> HashReturn { + let res = self.hasher.finalize_boxed(); + let mut ret = bits512_default(); + ret.copy_from_slice(&res); + HashReturn::BLAKE512(ret) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_blake512_hash() { + let input = "HelloWorld"; + let expected_output = "8dc77b2e140c3601a9fdd146684dea960124c514b999314be65fafe189cecee9bb1395cc80826aa1b8464de775678d13bfd332c51aafd026b9b5a67e606430f3"; + + let mut blake2 = BLAKE512::new(); + + blake2.digest(input); + + let result = blake2.complete().into_bytes(); + + let hash_out = crate::hex_table::u8_array_to_lower_hex_string(&result).unwrap(); + + assert_eq!(hash_out, expected_output); + } +}