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.
This commit is contained in:
Tobin C. Harding 2024-07-11 13:35:20 +10:00
parent 2fcd65ad97
commit 8dcecfc144
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
11 changed files with 45 additions and 88 deletions

View File

@ -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() }

View File

@ -35,14 +35,6 @@ impl<T: GeneralHash + str::FromStr> str::FromStr for Hmac<T> {
fn from_str(s: &str) -> Result<Self, Self::Err> { Ok(Hmac(str::FromStr::from_str(s)?)) }
}
/// Pair of underlying hash midstates which represent the current state of an `HmacEngine`.
pub struct HmacMidState<T: GeneralHash> {
/// Midstate of the inner hash engine
pub inner: <T::Engine as HashEngine>::MidState,
/// Midstate of the outer hash engine
pub outer: <T::Engine as HashEngine>::MidState,
}
/// Pair of underlying hash engines, used for the inner and outer hash of HMAC.
#[derive(Clone)]
pub struct HmacEngine<T: GeneralHash> {
@ -101,12 +93,6 @@ impl<T: GeneralHash> HmacEngine<T> {
}
impl<T: GeneralHash> HashEngine for HmacEngine<T> {
type MidState = HmacMidState<T>;
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() }

View File

@ -178,13 +178,6 @@ pub type HkdfSha512 = Hkdf<sha512::Hash>;
/// 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;

View File

@ -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 }

View File

@ -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 }

View File

@ -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::<Midstate>().expect("failed to parse hex");

View File

@ -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() }

View File

@ -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() }

View File

@ -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 }

View File

@ -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() }

View File

@ -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]