From 8dcecfc144673300a630d9cbd716cadecf68d0d1 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 11 Jul 2024 13:35:20 +1000 Subject: [PATCH] Remove midstate from the GeneralHash and HashEngine traits Midstates are not generic objects; they don't have universal cryptographic properties and if you are using them you should be using a specific midstate type. Therefore it shouldn't be part of `GeneralHash` or `HashEngine`. Furthermore, in practice it seems like `sha2` midstates are the only ones that anybody uses, at least in bitcoin. Remove the midstate stuff from the `GeneralHash` and `HashEngine` traits. Keep the `midstate` functionality as inherent functions if it is used internally. Keep the functionality on `sha256` as inherent public functions. --- hashes/src/hash160.rs | 3 --- hashes/src/hmac.rs | 14 -------------- hashes/src/lib.rs | 7 ------- hashes/src/ripemd160.rs | 14 ++++++-------- hashes/src/sha1.rs | 18 ++++++++---------- hashes/src/sha256.rs | 26 ++++++++++++++------------ hashes/src/sha256d.rs | 3 --- hashes/src/sha384.rs | 4 ---- hashes/src/sha512.rs | 34 ++++++++++++++++------------------ hashes/src/sha512_256.rs | 4 ---- hashes/src/siphash24.rs | 6 +----- 11 files changed, 45 insertions(+), 88 deletions(-) diff --git a/hashes/src/hash160.rs b/hashes/src/hash160.rs index 10cfeb2e3..ff884454e 100644 --- a/hashes/src/hash160.rs +++ b/hashes/src/hash160.rs @@ -32,9 +32,6 @@ impl Default for HashEngine { } impl crate::HashEngine for HashEngine { - type MidState = sha256::Midstate; - fn midstate(&self) -> Self::MidState { self.0.midstate() } - const BLOCK_SIZE: usize = 64; // Same as sha256::HashEngine::BLOCK_SIZE; fn input(&mut self, data: &[u8]) { self.0.input(data) } fn n_bytes_hashed(&self) -> usize { self.0.n_bytes_hashed() } diff --git a/hashes/src/hmac.rs b/hashes/src/hmac.rs index 1e0f60a06..e42d809bb 100644 --- a/hashes/src/hmac.rs +++ b/hashes/src/hmac.rs @@ -35,14 +35,6 @@ impl str::FromStr for Hmac { fn from_str(s: &str) -> Result { Ok(Hmac(str::FromStr::from_str(s)?)) } } -/// Pair of underlying hash midstates which represent the current state of an `HmacEngine`. -pub struct HmacMidState { - /// Midstate of the inner hash engine - pub inner: ::MidState, - /// Midstate of the outer hash engine - pub outer: ::MidState, -} - /// Pair of underlying hash engines, used for the inner and outer hash of HMAC. #[derive(Clone)] pub struct HmacEngine { @@ -101,12 +93,6 @@ impl HmacEngine { } impl HashEngine for HmacEngine { - type MidState = HmacMidState; - - fn midstate(&self) -> Self::MidState { - HmacMidState { inner: self.iengine.midstate(), outer: self.oengine.midstate() } - } - const BLOCK_SIZE: usize = T::Engine::BLOCK_SIZE; fn n_bytes_hashed(&self) -> usize { self.iengine.n_bytes_hashed() } diff --git a/hashes/src/lib.rs b/hashes/src/lib.rs index d54ccd564..c3bc39d67 100644 --- a/hashes/src/lib.rs +++ b/hashes/src/lib.rs @@ -178,13 +178,6 @@ pub type HkdfSha512 = Hkdf; /// A hashing engine which bytes can be serialized into. pub trait HashEngine: Clone + Default { - /// Byte array representing the internal state of the hash engine. - type MidState; - - /// Outputs the midstate of the hash engine. This function should not be - /// used directly unless you really know what you're doing. - fn midstate(&self) -> Self::MidState; - /// Length of the hash's internal block size, in bytes. const BLOCK_SIZE: usize; diff --git a/hashes/src/ripemd160.rs b/hashes/src/ripemd160.rs index eef1ad96f..60e01e086 100644 --- a/hashes/src/ripemd160.rs +++ b/hashes/src/ripemd160.rs @@ -60,14 +60,6 @@ impl HashEngine { buffer: [0; BLOCK_SIZE], } } -} - -impl Default for HashEngine { - fn default() -> Self { Self::new() } -} - -impl crate::HashEngine for HashEngine { - type MidState = [u8; 20]; #[cfg(not(hashes_fuzz))] fn midstate(&self) -> [u8; 20] { @@ -84,7 +76,13 @@ impl crate::HashEngine for HashEngine { ret.copy_from_slice(&self.buffer[..20]); ret } +} +impl Default for HashEngine { + fn default() -> Self { Self::new() } +} + +impl crate::HashEngine for HashEngine { const BLOCK_SIZE: usize = 64; fn n_bytes_hashed(&self) -> usize { self.length } diff --git a/hashes/src/sha1.rs b/hashes/src/sha1.rs index e0ce68354..6db4c0f0c 100644 --- a/hashes/src/sha1.rs +++ b/hashes/src/sha1.rs @@ -52,17 +52,9 @@ impl HashEngine { buffer: [0; BLOCK_SIZE], } } -} - -impl Default for HashEngine { - fn default() -> Self { Self::new() } -} - -impl crate::HashEngine for HashEngine { - type MidState = [u8; 20]; #[cfg(not(hashes_fuzz))] - fn midstate(&self) -> [u8; 20] { + pub(crate) fn midstate(&self) -> [u8; 20] { let mut ret = [0; 20]; for (val, ret_bytes) in self.h.iter().zip(ret.chunks_exact_mut(4)) { ret_bytes.copy_from_slice(&val.to_be_bytes()) @@ -71,12 +63,18 @@ impl crate::HashEngine for HashEngine { } #[cfg(hashes_fuzz)] - fn midstate(&self) -> [u8; 20] { + pub(crate) fn midstate(&self) -> [u8; 20] { let mut ret = [0; 20]; ret.copy_from_slice(&self.buffer[..20]); ret } +} +impl Default for HashEngine { + fn default() -> Self { Self::new() } +} + +impl crate::HashEngine for HashEngine { const BLOCK_SIZE: usize = 64; fn n_bytes_hashed(&self) -> usize { self.length } diff --git a/hashes/src/sha256.rs b/hashes/src/sha256.rs index 0c673e341..76aa3627c 100644 --- a/hashes/src/sha256.rs +++ b/hashes/src/sha256.rs @@ -71,17 +71,11 @@ impl HashEngine { buffer: [0; BLOCK_SIZE], } } -} - -impl Default for HashEngine { - fn default() -> Self { Self::new() } -} - -impl crate::HashEngine for HashEngine { - type MidState = Midstate; + /// Outputs the midstate of the hash engine. This function should not be + /// used directly unless you really know what you're doing. #[cfg(not(hashes_fuzz))] - fn midstate(&self) -> Midstate { + pub fn midstate(&self) -> Midstate { let mut ret = [0; 32]; for (val, ret_bytes) in self.h.iter().zip(ret.chunks_exact_mut(4)) { ret_bytes.copy_from_slice(&val.to_be_bytes()); @@ -89,13 +83,21 @@ impl crate::HashEngine for HashEngine { Midstate(ret) } + /// Outputs the midstate of the hash engine. This function should not be + /// used directly unless you really know what you're doing. #[cfg(hashes_fuzz)] - fn midstate(&self) -> Midstate { + pub fn midstate(&self) -> Midstate { let mut ret = [0; 32]; ret.copy_from_slice(&self.buffer[..32]); Midstate(ret) } +} +impl Default for HashEngine { + fn default() -> Self { Self::new() } +} + +impl crate::HashEngine for HashEngine { const BLOCK_SIZE: usize = 64; fn n_bytes_hashed(&self) -> usize { self.length } @@ -895,7 +897,7 @@ mod tests { #[test] #[rustfmt::skip] - fn midstate() { + pub(crate) fn midstate() { // Test vector obtained by doing an asset issuance on Elements let mut engine = sha256::Hash::engine(); // sha256dhash of outpoint @@ -1001,7 +1003,7 @@ mod tests { } #[test] - fn midstate_fmt_roundtrip() { + pub(crate) fn midstate_fmt_roundtrip() { let midstate = Midstate::hash_tag(b"ArbitraryTag"); let hex = format!("{}", midstate); let rinsed = hex.parse::().expect("failed to parse hex"); diff --git a/hashes/src/sha256d.rs b/hashes/src/sha256d.rs index 040436603..2a3456925 100644 --- a/hashes/src/sha256d.rs +++ b/hashes/src/sha256d.rs @@ -27,9 +27,6 @@ impl Default for HashEngine { } impl crate::HashEngine for HashEngine { - type MidState = sha256::Midstate; - fn midstate(&self) -> Self::MidState { self.0.midstate() } - const BLOCK_SIZE: usize = 64; // Same as sha256::HashEngine::BLOCK_SIZE; fn input(&mut self, data: &[u8]) { self.0.input(data) } fn n_bytes_hashed(&self) -> usize { self.0.n_bytes_hashed() } diff --git a/hashes/src/sha384.rs b/hashes/src/sha384.rs index 900d542c7..0a69651df 100644 --- a/hashes/src/sha384.rs +++ b/hashes/src/sha384.rs @@ -33,10 +33,6 @@ impl Default for HashEngine { } impl crate::HashEngine for HashEngine { - type MidState = [u8; 64]; - - fn midstate(&self) -> [u8; 64] { self.0.midstate() } - const BLOCK_SIZE: usize = sha512::BLOCK_SIZE; fn n_bytes_hashed(&self) -> usize { self.0.n_bytes_hashed() } diff --git a/hashes/src/sha512.rs b/hashes/src/sha512.rs index 8dd2f6024..ac30a67b2 100644 --- a/hashes/src/sha512.rs +++ b/hashes/src/sha512.rs @@ -72,6 +72,22 @@ impl Default for HashEngine { } impl HashEngine { + #[cfg(not(hashes_fuzz))] + pub(crate) fn midstate(&self) -> [u8; 64] { + let mut ret = [0; 64]; + for (val, ret_bytes) in self.h.iter().zip(ret.chunks_exact_mut(8)) { + ret_bytes.copy_from_slice(&val.to_be_bytes()); + } + ret + } + + #[cfg(hashes_fuzz)] + pub(crate) fn midstate(&self) -> [u8; 64] { + let mut ret = [0; 64]; + ret.copy_from_slice(&self.buffer[..64]); + ret + } + /// Constructs a hash engine suitable for use constructing a `sha512_256::HashEngine`. #[rustfmt::skip] pub(crate) const fn sha512_256() -> Self { @@ -100,24 +116,6 @@ impl HashEngine { } impl crate::HashEngine for HashEngine { - type MidState = [u8; 64]; - - #[cfg(not(hashes_fuzz))] - fn midstate(&self) -> [u8; 64] { - let mut ret = [0; 64]; - for (val, ret_bytes) in self.h.iter().zip(ret.chunks_exact_mut(8)) { - ret_bytes.copy_from_slice(&val.to_be_bytes()); - } - ret - } - - #[cfg(hashes_fuzz)] - fn midstate(&self) -> [u8; 64] { - let mut ret = [0; 64]; - ret.copy_from_slice(&self.buffer[..64]); - ret - } - const BLOCK_SIZE: usize = 128; fn n_bytes_hashed(&self) -> usize { self.length } diff --git a/hashes/src/sha512_256.rs b/hashes/src/sha512_256.rs index d08a0eae2..01edbd98d 100644 --- a/hashes/src/sha512_256.rs +++ b/hashes/src/sha512_256.rs @@ -43,10 +43,6 @@ impl Default for HashEngine { } impl crate::HashEngine for HashEngine { - type MidState = [u8; 64]; - - fn midstate(&self) -> [u8; 64] { self.0.midstate() } - const BLOCK_SIZE: usize = sha512::BLOCK_SIZE; fn n_bytes_hashed(&self) -> usize { self.0.n_bytes_hashed() } diff --git a/hashes/src/siphash24.rs b/hashes/src/siphash24.rs index 6ba153fd4..4e51cd79c 100644 --- a/hashes/src/siphash24.rs +++ b/hashes/src/siphash24.rs @@ -19,7 +19,7 @@ fn from_engine(e: HashEngine) -> Hash { Hash::from_u64(Hash::from_engine_to_u64( #[cfg(hashes_fuzz)] fn from_engine(e: HashEngine) -> Hash { - let state = e.midstate(); + let state = e.state.clone(); Hash::from_u64(state.v0 ^ state.v1 ^ state.v2 ^ state.v3) } @@ -133,10 +133,6 @@ impl Default for HashEngine { } impl crate::HashEngine for HashEngine { - type MidState = State; - - fn midstate(&self) -> State { self.state.clone() } - const BLOCK_SIZE: usize = 8; #[inline]