From e1bac7da55c4809367facc2e242c0d76ddcf6ac2 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 20 Feb 2025 13:02:09 +1100 Subject: [PATCH] Bound HmacEngine on HashEngine We would like to do away with the `GeneralHash` trait. Currently we bound `Hmac` and `HmacEngine` on it but this is unnecessary now that we have added `HashEngine::finalize` and `HashEngine::Hash`. Bound the `HmacEngine` on `HashEngine` (which has an associated `Hash` type returned by `finilalize`). Bound `Hmac` type on `T::Hash` where `T` is `HashEngine`. Includes some minor shortening of local variable names around hmac engine usage. Note this means that `Hmac` no longer implements `GeneralHash`. --- bitcoin/src/bip32.rs | 43 +++++++------- hashes/src/hash160/mod.rs | 1 + hashes/src/hkdf/mod.rs | 40 ++++++------- hashes/src/hmac/mod.rs | 105 +++++++++++++++-------------------- hashes/src/lib.rs | 6 ++ hashes/src/ripemd160/mod.rs | 1 + hashes/src/sha1/mod.rs | 1 + hashes/src/sha256/mod.rs | 1 + hashes/src/sha256d/mod.rs | 1 + hashes/src/sha256t/mod.rs | 1 + hashes/src/sha384/mod.rs | 1 + hashes/src/sha512/mod.rs | 1 + hashes/src/sha512_256/mod.rs | 1 + hashes/src/siphash24/mod.rs | 1 + hashes/tests/regression.rs | 10 ++-- io/src/hash.rs | 24 ++++---- 16 files changed, 117 insertions(+), 121 deletions(-) diff --git a/bitcoin/src/bip32.rs b/bitcoin/src/bip32.rs index a25ff424d..5b83327e8 100644 --- a/bitcoin/src/bip32.rs +++ b/bitcoin/src/bip32.rs @@ -10,7 +10,7 @@ use core::ops::Index; use core::str::FromStr; use core::{fmt, slice}; -use hashes::{hash160, hash_newtype, sha512, GeneralHash, HashEngine, Hmac, HmacEngine}; +use hashes::{hash160, hash_newtype, sha512, HashEngine, Hmac, HmacEngine}; use internals::write_err; use secp256k1::{Secp256k1, XOnlyPublicKey}; @@ -584,9 +584,9 @@ impl From for Error { impl Xpriv { /// Constructs a new master key from a seed value pub fn new_master(network: impl Into, seed: &[u8]) -> Result { - let mut hmac_engine: HmacEngine = HmacEngine::new(b"Bitcoin seed"); - hmac_engine.input(seed); - let hmac_result: Hmac = Hmac::from_engine(hmac_engine); + let mut engine = HmacEngine::::new(b"Bitcoin seed"); + engine.input(seed); + let hmac = engine.finalize(); Ok(Xpriv { network: network.into(), @@ -594,9 +594,9 @@ impl Xpriv { parent_fingerprint: Default::default(), child_number: ChildNumber::ZERO_NORMAL, private_key: secp256k1::SecretKey::from_byte_array( - &hmac_result.as_ref()[..32].try_into().expect("Slice should be exactly 32 bytes"), + &hmac.as_ref()[..32].try_into().expect("Slice should be exactly 32 bytes"), )?, - chain_code: ChainCode::from_hmac(hmac_result), + chain_code: ChainCode::from_hmac(hmac), }) } @@ -650,25 +650,25 @@ impl Xpriv { /// Private->Private child key derivation fn ckd_priv(&self, secp: &Secp256k1, i: ChildNumber) -> Xpriv { - let mut hmac_engine: HmacEngine = HmacEngine::new(&self.chain_code[..]); + let mut engine = HmacEngine::::new(&self.chain_code[..]); match i { ChildNumber::Normal { .. } => { // Non-hardened key: compute public data and use that - hmac_engine.input( + engine.input( &secp256k1::PublicKey::from_secret_key(secp, &self.private_key).serialize()[..], ); } ChildNumber::Hardened { .. } => { // Hardened key: use only secret data to prevent public derivation - hmac_engine.input(&[0u8]); - hmac_engine.input(&self.private_key[..]); + engine.input(&[0u8]); + engine.input(&self.private_key[..]); } } - hmac_engine.input(&u32::from(i).to_be_bytes()); - let hmac_result: Hmac = Hmac::from_engine(hmac_engine); + engine.input(&u32::from(i).to_be_bytes()); + let hmac: Hmac = engine.finalize(); let sk = secp256k1::SecretKey::from_byte_array( - &hmac_result.as_ref()[..32].try_into().expect("statistically impossible to hit"), + &hmac.as_ref()[..32].try_into().expect("statistically impossible to hit"), ) .expect("statistically impossible to hit"); let tweaked = @@ -680,7 +680,7 @@ impl Xpriv { parent_fingerprint: self.fingerprint(secp), child_number: i, private_key: tweaked, - chain_code: ChainCode::from_hmac(hmac_result), + chain_code: ChainCode::from_hmac(hmac), } } @@ -812,18 +812,15 @@ impl Xpub { match i { ChildNumber::Hardened { .. } => Err(Error::CannotDeriveFromHardenedKey), ChildNumber::Normal { index: n } => { - let mut hmac_engine: HmacEngine = - HmacEngine::new(&self.chain_code[..]); - hmac_engine.input(&self.public_key.serialize()[..]); - hmac_engine.input(&n.to_be_bytes()); + let mut engine = HmacEngine::::new(&self.chain_code[..]); + engine.input(&self.public_key.serialize()[..]); + engine.input(&n.to_be_bytes()); - let hmac_result: Hmac = Hmac::from_engine(hmac_engine); + let hmac = engine.finalize(); let private_key = secp256k1::SecretKey::from_byte_array( - &hmac_result.as_ref()[..32] - .try_into() - .expect("Slice should be exactly 32 bytes"), + &hmac.as_ref()[..32].try_into().expect("Slice should be exactly 32 bytes"), )?; - let chain_code = ChainCode::from_hmac(hmac_result); + let chain_code = ChainCode::from_hmac(hmac); Ok((private_key, chain_code)) } } diff --git a/hashes/src/hash160/mod.rs b/hashes/src/hash160/mod.rs index 328ad9513..bf03d1d1f 100644 --- a/hashes/src/hash160/mod.rs +++ b/hashes/src/hash160/mod.rs @@ -39,6 +39,7 @@ impl Default for HashEngine { impl crate::HashEngine for HashEngine { type Hash = Hash; + type Bytes = [u8; 20]; const BLOCK_SIZE: usize = 64; // Same as sha256::HashEngine::BLOCK_SIZE; fn input(&mut self, data: &[u8]) { self.0.input(data) } diff --git a/hashes/src/hkdf/mod.rs b/hashes/src/hkdf/mod.rs index f02e0dd47..c381422da 100644 --- a/hashes/src/hkdf/mod.rs +++ b/hashes/src/hkdf/mod.rs @@ -11,7 +11,7 @@ use alloc::vec; use alloc::vec::Vec; use core::fmt; -use crate::{GeneralHash, HashEngine, Hmac, HmacEngine, IsByteArray}; +use crate::{HashEngine, Hmac, HmacEngine, IsByteArray}; /// Output keying material max length multiple. const MAX_OUTPUT_BLOCKS: usize = 255; @@ -33,20 +33,20 @@ impl std::error::Error for MaxLengthError {} /// HMAC-based Extract-and-Expand Key Derivation Function (HKDF). #[derive(Copy, Clone)] -pub struct Hkdf { +pub struct Hkdf { /// Pseudorandom key based on the extract step. - prk: Hmac, + prk: Hmac, } -impl Hkdf +impl Hkdf where - ::Engine: Default, + T: Default, { /// Initialize a HKDF by performing the extract step. pub fn new(salt: &[u8], ikm: &[u8]) -> Self { - let mut hmac_engine: HmacEngine = HmacEngine::new(salt); - hmac_engine.input(ikm); - Self { prk: Hmac::from_engine(hmac_engine) } + let mut engine: HmacEngine = HmacEngine::new(salt); + engine.input(ikm); + Self { prk: engine.finalize() } } /// Expand the key to generate output key material in okm. @@ -65,19 +65,19 @@ where let total_blocks = (okm.len() + T::Bytes::LEN - 1) / T::Bytes::LEN; while counter <= total_blocks as u8 { - let mut hmac_engine: HmacEngine = HmacEngine::new(self.prk.as_ref()); + let mut engine: HmacEngine = HmacEngine::new(self.prk.as_ref()); // First block does not have a previous block, // all other blocks include last block in the HMAC input. if counter != 1u8 { let previous_start_index = (counter as usize - 2) * T::Bytes::LEN; let previous_end_index = (counter as usize - 1) * T::Bytes::LEN; - hmac_engine.input(&okm[previous_start_index..previous_end_index]); + engine.input(&okm[previous_start_index..previous_end_index]); } - hmac_engine.input(info); - hmac_engine.input(&[counter]); + engine.input(info); + engine.input(&[counter]); - let t = Hmac::from_engine(hmac_engine); + let t = engine.finalize(); let start_index = (counter as usize - 1) * T::Bytes::LEN; // Last block might not take full hash length. let end_index = if counter == (total_blocks as u8) { @@ -106,7 +106,7 @@ where } } -impl fmt::Debug for Hkdf { +impl fmt::Debug for Hkdf { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use crate::{sha256t, sha256t_tag}; @@ -141,7 +141,7 @@ mod tests { let ikm = Vec::from_hex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(); let info = Vec::from_hex("f0f1f2f3f4f5f6f7f8f9").unwrap(); - let hkdf = Hkdf::::new(&salt, &ikm); + let hkdf = Hkdf::::new(&salt, &ikm); let mut okm = [0u8; 42]; hkdf.expand(&info, &mut okm).unwrap(); @@ -163,7 +163,7 @@ mod tests { "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff" ).unwrap(); - let hkdf = Hkdf::::new(&salt, &ikm); + let hkdf = Hkdf::::new(&salt, &ikm); let mut okm = [0u8; 82]; hkdf.expand(&info, &mut okm).unwrap(); @@ -179,7 +179,7 @@ mod tests { let ikm = Vec::from_hex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(); let info = Vec::from_hex("f0f1f2f3f4f5f6f7f8f9").unwrap(); - let hkdf = Hkdf::::new(&salt, &ikm); + let hkdf = Hkdf::::new(&salt, &ikm); let mut okm = [0u8; 256 * 32]; let e = hkdf.expand(&info, &mut okm); @@ -192,7 +192,7 @@ mod tests { let ikm = Vec::from_hex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(); let info = Vec::from_hex("f0f1f2f3f4f5f6f7f8f9").unwrap(); - let hkdf = Hkdf::::new(&salt, &ikm); + let hkdf = Hkdf::::new(&salt, &ikm); let mut okm = [0u8; 1]; hkdf.expand(&info, &mut okm).unwrap(); @@ -205,7 +205,7 @@ mod tests { let ikm = Vec::from_hex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(); let info = Vec::from_hex("f0f1f2f3f4f5f6f7f8f9").unwrap(); - let hkdf = Hkdf::::new(&salt, &ikm); + let hkdf = Hkdf::::new(&salt, &ikm); let okm = hkdf.expand_to_len(&info, 42).unwrap(); assert_eq!( @@ -219,7 +219,7 @@ mod tests { let salt = Vec::from_hex("000102030405060708090a0b0c").unwrap(); let ikm = Vec::from_hex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(); - let hkdf = Hkdf::::new(&salt, &ikm); + let hkdf = Hkdf::::new(&salt, &ikm); let debug = alloc::format!("{:?}", hkdf); assert_eq!(debug, "Hkdf(#ec7bd36ab2ed4045)"); diff --git a/hashes/src/hmac/mod.rs b/hashes/src/hmac/mod.rs index fa50389db..2d70253fc 100644 --- a/hashes/src/hmac/mod.rs +++ b/hashes/src/hmac/mod.rs @@ -12,36 +12,26 @@ use core::{convert, fmt, str}; #[cfg(feature = "serde")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use crate::{GeneralHash, Hash, HashEngine}; +use crate::{Hash, HashEngine}; /// A hash computed from a RFC 2104 HMAC. Parameterized by the underlying hash function. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] -pub struct Hmac(T); +pub struct Hmac(T); -impl Hmac { - /// Constructs a new keyed HMAC engine from `key`. - pub fn engine(key: &[u8]) -> HmacEngine - where - ::Engine: Default, - { - HmacEngine::new(key) - } -} - -impl str::FromStr for Hmac { +impl str::FromStr for Hmac { type Err = ::Err; fn from_str(s: &str) -> Result { Ok(Hmac(str::FromStr::from_str(s)?)) } } /// Pair of underlying hash engines, used for the inner and outer hash of HMAC. #[derive(Debug, Clone)] -pub struct HmacEngine { - iengine: T::Engine, - oengine: T::Engine, +pub struct HmacEngine { + iengine: T, + oengine: T, } -impl HmacEngine { +impl HmacEngine { /// Constructs a new keyed HMAC engine from `key`. /// /// We only support underlying hashes whose block sizes are ≤ 128 bytes. @@ -51,24 +41,23 @@ impl HmacEngine { /// Larger hashes will result in a panic. pub fn new(key: &[u8]) -> HmacEngine where - ::Engine: Default, + T: Default, { - debug_assert!(T::Engine::BLOCK_SIZE <= 128); + debug_assert!(T::BLOCK_SIZE <= 128); let mut ipad = [0x36u8; 128]; let mut opad = [0x5cu8; 128]; - let mut ret = HmacEngine { - iengine: ::engine(), - oengine: ::engine(), - }; + let mut ret = HmacEngine { iengine: T::default(), oengine: T::default() }; - if key.len() > T::Engine::BLOCK_SIZE { - let hash = ::hash(key); - let hash = hash.as_byte_array().as_ref(); - for (b_i, b_h) in ipad.iter_mut().zip(hash) { + if key.len() > T::BLOCK_SIZE { + let mut engine = T::default(); + engine.input(key); + let hash = engine.finalize(); + + for (b_i, b_h) in ipad.iter_mut().zip(hash.as_ref()) { *b_i ^= *b_h; } - for (b_o, b_h) in opad.iter_mut().zip(hash) { + for (b_o, b_h) in opad.iter_mut().zip(hash.as_ref()) { *b_o ^= *b_h; } } else { @@ -80,55 +69,49 @@ impl HmacEngine { } }; - HashEngine::input(&mut ret.iengine, &ipad[..T::Engine::BLOCK_SIZE]); - HashEngine::input(&mut ret.oengine, &opad[..T::Engine::BLOCK_SIZE]); + ret.iengine.input(&ipad[..T::BLOCK_SIZE]); + ret.oengine.input(&opad[..T::BLOCK_SIZE]); ret } /// A special constructor giving direct access to the underlying "inner" and "outer" engines. - pub fn from_inner_engines(iengine: T::Engine, oengine: T::Engine) -> HmacEngine { + pub fn from_inner_engines(iengine: T, oengine: T) -> HmacEngine { HmacEngine { iengine, oengine } } } -impl HashEngine for HmacEngine { - type Hash = Hmac; - const BLOCK_SIZE: usize = T::Engine::BLOCK_SIZE; +impl HashEngine for HmacEngine { + type Hash = Hmac; + type Bytes = T::Bytes; + const BLOCK_SIZE: usize = T::BLOCK_SIZE; fn n_bytes_hashed(&self) -> u64 { self.iengine.n_bytes_hashed() } fn input(&mut self, buf: &[u8]) { self.iengine.input(buf) } - fn finalize(self) -> Self::Hash { Hmac::from_engine(self) } + fn finalize(mut self) -> Self::Hash { + let ihash = self.iengine.finalize(); + self.oengine.input(ihash.as_ref()); + Hmac(self.oengine.finalize()) + } } -impl fmt::Debug for Hmac { +impl fmt::Debug for Hmac { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.0, f) } } -impl fmt::Display for Hmac { +impl fmt::Display for Hmac { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) } } -impl fmt::LowerHex for Hmac { +impl fmt::LowerHex for Hmac { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) } } -impl convert::AsRef<[u8]> for Hmac { +impl convert::AsRef<[u8]> for Hmac { // Calling as_byte_array is more reliable fn as_ref(&self) -> &[u8] { self.0.as_byte_array().as_ref() } } -impl GeneralHash for Hmac { - type Engine = HmacEngine; - - fn from_engine(mut e: HmacEngine) -> Hmac { - let ihash = T::from_engine(e.iengine); - e.oengine.input(ihash.as_byte_array().as_ref()); - let ohash = T::from_engine(e.oengine); - Hmac(ohash) - } -} - -impl Hash for Hmac { +impl Hash for Hmac { type Bytes = T::Bytes; fn from_byte_array(bytes: T::Bytes) -> Self { Hmac(T::from_byte_array(bytes)) } @@ -144,14 +127,14 @@ impl Hash for Hmac { } #[cfg(feature = "serde")] -impl Serialize for Hmac { +impl Serialize for Hmac { fn serialize(&self, s: S) -> Result { Serialize::serialize(&self.0, s) } } #[cfg(feature = "serde")] -impl<'de, T: GeneralHash + Deserialize<'de>> Deserialize<'de> for Hmac { +impl<'de, T: Hash + Deserialize<'de>> Deserialize<'de> for Hmac { fn deserialize>(d: D) -> Result, D::Error> { let bytes = Deserialize::deserialize(d)?; Ok(Hmac(bytes)) @@ -166,14 +149,14 @@ crate::internal_macros::impl_write!( Ok(buf.len()) }, |_us| { Ok(()) }, - T: crate::GeneralHash + T: crate::HashEngine ); #[cfg(test)] mod tests { #[test] fn test() { - use crate::{sha256, GeneralHash as _, Hash as _, HashEngine, Hmac, HmacEngine}; + use crate::{sha256, Hash as _, HashEngine, HmacEngine}; #[derive(Clone)] struct Test { @@ -288,9 +271,9 @@ mod tests { ]; for test in tests { - let mut engine = HmacEngine::::new(test.key); + let mut engine = HmacEngine::::new(test.key); engine.input(test.input); - let hash = Hmac::::from_engine(engine); + let hash = engine.finalize(); assert_eq!(hash.as_ref(), test.output); assert_eq!(hash.to_byte_array(), test.output); } @@ -331,11 +314,11 @@ mod tests { mod benches { use test::Bencher; - use crate::{sha256, GeneralHash as _, HashEngine, Hmac}; + use crate::{sha256, HashEngine as _, HmacEngine}; #[bench] pub fn hmac_sha256_10(bh: &mut Bencher) { - let mut engine = Hmac::::engine(&[]); + let mut engine = HmacEngine::::new(&[]); let bytes = [1u8; 10]; bh.iter(|| { engine.input(&bytes); @@ -345,7 +328,7 @@ mod benches { #[bench] pub fn hmac_sha256_1k(bh: &mut Bencher) { - let mut engine = Hmac::::engine(&[]); + let mut engine = HmacEngine::::new(&[]); let bytes = [1u8; 1024]; bh.iter(|| { engine.input(&bytes); @@ -355,7 +338,7 @@ mod benches { #[bench] pub fn hmac_sha256_64k(bh: &mut Bencher) { - let mut engine = Hmac::::engine(&[]); + let mut engine = HmacEngine::::new(&[]); let bytes = [1u8; 65536]; bh.iter(|| { engine.input(&bytes); diff --git a/hashes/src/lib.rs b/hashes/src/lib.rs index 329273b94..4201b0ea0 100644 --- a/hashes/src/lib.rs +++ b/hashes/src/lib.rs @@ -189,6 +189,12 @@ pub trait HashEngine: Clone { /// The `Hash` type returned when finalizing this engine. type Hash: Hash; + /// The byte array that is used internally in `finalize`. + type Bytes: Copy + IsByteArray; + + /// Length of the hash, in bytes. + const LEN: usize = Self::Bytes::LEN; + /// Length of the hash's internal block size, in bytes. const BLOCK_SIZE: usize; diff --git a/hashes/src/ripemd160/mod.rs b/hashes/src/ripemd160/mod.rs index c91dc8b68..d6ec93f9d 100644 --- a/hashes/src/ripemd160/mod.rs +++ b/hashes/src/ripemd160/mod.rs @@ -88,6 +88,7 @@ impl Default for HashEngine { impl crate::HashEngine for HashEngine { type Hash = Hash; + type Bytes = [u8; 20]; const BLOCK_SIZE: usize = 64; fn n_bytes_hashed(&self) -> u64 { self.bytes_hashed } diff --git a/hashes/src/sha1/mod.rs b/hashes/src/sha1/mod.rs index 6abbf0a9c..18f620253 100644 --- a/hashes/src/sha1/mod.rs +++ b/hashes/src/sha1/mod.rs @@ -80,6 +80,7 @@ impl Default for HashEngine { impl crate::HashEngine for HashEngine { type Hash = Hash; + type Bytes = [u8; 20]; const BLOCK_SIZE: usize = 64; fn n_bytes_hashed(&self) -> u64 { self.bytes_hashed } diff --git a/hashes/src/sha256/mod.rs b/hashes/src/sha256/mod.rs index fd40401bd..323e4de8f 100644 --- a/hashes/src/sha256/mod.rs +++ b/hashes/src/sha256/mod.rs @@ -129,6 +129,7 @@ impl Default for HashEngine { impl crate::HashEngine for HashEngine { type Hash = Hash; + type Bytes = [u8; 32]; const BLOCK_SIZE: usize = 64; fn n_bytes_hashed(&self) -> u64 { self.bytes_hashed } diff --git a/hashes/src/sha256d/mod.rs b/hashes/src/sha256d/mod.rs index 313760852..69bb8a72a 100644 --- a/hashes/src/sha256d/mod.rs +++ b/hashes/src/sha256d/mod.rs @@ -34,6 +34,7 @@ impl Default for HashEngine { impl crate::HashEngine for HashEngine { type Hash = Hash; + type Bytes = [u8; 32]; const BLOCK_SIZE: usize = 64; // Same as sha256::HashEngine::BLOCK_SIZE; fn input(&mut self, data: &[u8]) { self.0.input(data) } diff --git a/hashes/src/sha256t/mod.rs b/hashes/src/sha256t/mod.rs index 7b58bc991..11e224058 100644 --- a/hashes/src/sha256t/mod.rs +++ b/hashes/src/sha256t/mod.rs @@ -134,6 +134,7 @@ impl Clone for HashEngine { impl crate::HashEngine for HashEngine { type Hash = Hash; + type Bytes = [u8; 32]; const BLOCK_SIZE: usize = 64; // Same as sha256::HashEngine::BLOCK_SIZE; fn input(&mut self, data: &[u8]) { self.0.input(data) } diff --git a/hashes/src/sha384/mod.rs b/hashes/src/sha384/mod.rs index 9918afa2f..3d6538af0 100644 --- a/hashes/src/sha384/mod.rs +++ b/hashes/src/sha384/mod.rs @@ -31,6 +31,7 @@ impl Default for HashEngine { impl crate::HashEngine for HashEngine { type Hash = Hash; + type Bytes = [u8; 48]; const BLOCK_SIZE: usize = sha512::BLOCK_SIZE; fn n_bytes_hashed(&self) -> u64 { self.0.n_bytes_hashed() } diff --git a/hashes/src/sha512/mod.rs b/hashes/src/sha512/mod.rs index 617f34cd8..0256cde21 100644 --- a/hashes/src/sha512/mod.rs +++ b/hashes/src/sha512/mod.rs @@ -121,6 +121,7 @@ impl HashEngine { impl crate::HashEngine for HashEngine { type Hash = Hash; + type Bytes = [u8; 64]; const BLOCK_SIZE: usize = 128; fn n_bytes_hashed(&self) -> u64 { self.bytes_hashed } diff --git a/hashes/src/sha512_256/mod.rs b/hashes/src/sha512_256/mod.rs index 04e6d9be3..cf12d4604 100644 --- a/hashes/src/sha512_256/mod.rs +++ b/hashes/src/sha512_256/mod.rs @@ -41,6 +41,7 @@ impl Default for HashEngine { impl crate::HashEngine for HashEngine { type Hash = Hash; + type Bytes = [u8; 64]; const BLOCK_SIZE: usize = sha512::BLOCK_SIZE; fn n_bytes_hashed(&self) -> u64 { self.0.n_bytes_hashed() } diff --git a/hashes/src/siphash24/mod.rs b/hashes/src/siphash24/mod.rs index 4f8de24ff..50abe8575 100644 --- a/hashes/src/siphash24/mod.rs +++ b/hashes/src/siphash24/mod.rs @@ -122,6 +122,7 @@ impl HashEngine { impl crate::HashEngine for HashEngine { type Hash = Hash; + type Bytes = [u8; 8]; const BLOCK_SIZE: usize = 8; #[inline] diff --git a/hashes/tests/regression.rs b/hashes/tests/regression.rs index 2bacd7ff2..31aeec5f8 100644 --- a/hashes/tests/regression.rs +++ b/hashes/tests/regression.rs @@ -8,7 +8,7 @@ use bitcoin_hashes::{ hash160, ripemd160, sha1, sha256, sha256d, sha256t, sha384, sha512, sha512_256, siphash24, - GeneralHash as _, HashEngine as _, Hmac, HmacEngine, + HashEngine as _, HmacEngine, }; const DATA: &str = "arbitrary data to hash as a regression test"; @@ -57,9 +57,9 @@ fn regression_sha256t() { #[test] fn regression_hmac_sha256_with_key() { - let mut engine = HmacEngine::::new(HMAC_KEY); + let mut engine = HmacEngine::::new(HMAC_KEY); engine.input(DATA.as_bytes()); - let hash = Hmac::from_engine(engine); + let hash = engine.finalize(); let got = format!("{}", hash); let want = "d159cecaf4adf90b6a641bab767e4817d3a51c414acea3682686c35ec0b37b52"; @@ -68,9 +68,9 @@ fn regression_hmac_sha256_with_key() { #[test] fn regression_hmac_sha512_with_key() { - let mut engine = HmacEngine::::new(HMAC_KEY); + let mut engine = HmacEngine::::new(HMAC_KEY); engine.input(DATA.as_bytes()); - let hash = Hmac::from_engine(engine); + let hash = engine.finalize(); let got = format!("{}", hash); let want = "8511773748f89ba22c07fb3a2981a12c1823695119de41f4a62aead6b848bd34939acf16475c35ed7956114fead3e794cc162ecd35e447a4dabc3227d55f757b"; diff --git a/io/src/hash.rs b/io/src/hash.rs index a6a364e94..6a311b8fd 100644 --- a/io/src/hash.rs +++ b/io/src/hash.rs @@ -128,7 +128,7 @@ impl_write!( Ok(buf.len()) }, |_us| { Ok(()) }, - T: hashes::GeneralHash + T: hashes::HashEngine ); /// Hashes data from a reader. @@ -172,7 +172,7 @@ mod sealed { mod tests { use alloc::format; - use hashes::{hmac, Hmac}; + use hashes::hmac; use super::*; use crate::{Cursor, Write as _}; @@ -257,24 +257,24 @@ mod tests { #[test] fn hmac() { - let mut engine = hmac::HmacEngine::::new(&[0xde, 0xad, 0xbe, 0xef]); + let mut engine = hmac::HmacEngine::::new(&[0xde, 0xad, 0xbe, 0xef]); engine.write_all(&[]).unwrap(); assert_eq!( - format!("{}", hmac::Hmac::from_engine(engine)), + format!("{}", engine.finalize()), "bf5515149cf797955c4d3194cca42472883281951697c8375d9d9b107f384225" ); - let mut engine = hmac::HmacEngine::::new(&[0xde, 0xad, 0xbe, 0xef]); + let mut engine = hmac::HmacEngine::::new(&[0xde, 0xad, 0xbe, 0xef]); engine.write_all(&[1; 256]).unwrap(); assert_eq!( - format!("{}", hmac::Hmac::from_engine(engine)), + format!("{}", engine.finalize()), "59c9aca10c81c73cb4c196d94db741b6bf2050e0153d5a45f2526bff34675ac5" ); - let mut engine = hmac::HmacEngine::::new(&[0xde, 0xad, 0xbe, 0xef]); + let mut engine = hmac::HmacEngine::::new(&[0xde, 0xad, 0xbe, 0xef]); engine.write_all(&[99; 64000]).unwrap(); assert_eq!( - format!("{}", hmac::Hmac::from_engine(engine)), + format!("{}", engine.finalize()), "30df499717415a395379a1eaabe50038036e4abb5afc94aa55c952f4aa57be08" ); } @@ -345,9 +345,9 @@ mod tests { #[test] fn regression_hmac_sha256_with_key() { - let mut engine = HmacEngine::::new(HMAC_KEY); + let mut engine = HmacEngine::::new(HMAC_KEY); engine.input(DATA.as_bytes()); - let hash = Hmac::from_engine(engine); + let hash = engine.finalize(); let got = format!("{}", hash); let want = "d159cecaf4adf90b6a641bab767e4817d3a51c414acea3682686c35ec0b37b52"; @@ -356,9 +356,9 @@ mod tests { #[test] fn regression_hmac_sha512_with_key() { - let mut engine = HmacEngine::::new(HMAC_KEY); + let mut engine = HmacEngine::::new(HMAC_KEY); engine.input(DATA.as_bytes()); - let hash = Hmac::from_engine(engine); + let hash = engine.finalize(); let got = format!("{}", hash); let want = "8511773748f89ba22c07fb3a2981a12c1823695119de41f4a62aead6b848bd34939acf16475c35ed7956114fead3e794cc162ecd35e447a4dabc3227d55f757b";