hashes: Remove Bytes and LEN from HashEngine
What changed, and why it matters
This is a routine code cleanup in the rust-bitcoin hashes library. It removes duplicate ways of asking a hash engine for the output length and byte type, directing callers to use the associated Hash type instead. The commit message explicitly says this fixes an inconsistency discovered for the sha512_256 output size, but the change itself is an API simplification, not a security patch. There is no evidence of a vulnerability being fixed.
No security action required. Treat as a normal API refactor. Downstream users relying on `HashEngine::Bytes` or `HashEngine::LEN` will need to migrate to `HashEngine::Hash::Bytes` and `HashEngine::Hash::LEN`.
Security signals we found
No cryptographic algorithm changes
No input validation changes
No memory safety changes
API surface reduction only
Commit message mentions resolving an inconsistency, not a vulnerability
Evidence from the diff
The patch removes the Bytes associated type and LEN constant from the HashEngine trait. Implementations of HashEngine for hash160, ripemd160, sha1, sha256, sha256d, sha256t, sha384, sha3_256, sha512, sha512_256, and siphash24 lose their type Bytes = [u8; N] declarations. Call sites in HKDF expansion are updated from T::Bytes::LEN to T::Hash::LEN. The commit message notes this resolves an inconsistency between HashEngine and Hash for sha512_256 output size, where the engine previously exposed a 64-byte Bytes type while the actual hash output is 32 bytes. The change is purely API surface simplification; no cryptographic logic, padding, or finalization code is modified.
Changed components
hashes/src/lib.rs (HashEngine trait)hashes/src/hkdf/mod.rs (HKDF expand logic)hashes/src/hmac/mod.rs (HmacEngine trait impl)hashes/src/hash160/mod.rshashes/src/ripemd160/mod.rshashes/src/sha1/mod.rshashes/src/sha256/mod.rshashes/src/sha256d/mod.rshashes/src/sha256t/mod.rshashes/src/sha384/mod.rshashes/src/sha3_256/mod.rshashes/src/sha512/mod.rshashes/src/sha512_256/mod.rshashes/src/siphash24/mod.rsInspect captured patch +8 / −26
diff --git a/hashes/src/hash160/mod.rs b/hashes/src/hash160/mod.rs
index 53309bd0..f4996abe 100644
--- a/hashes/src/hash160/mod.rs
+++ b/hashes/src/hash160/mod.rs
@@ -43,7 +43,6 @@ 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 95a29046..2129b53e 100644
--- a/hashes/src/hkdf/mod.rs
+++ b/hashes/src/hkdf/mod.rs
@@ -10,7 +10,7 @@ use alloc::vec;
use alloc::vec::Vec;
use core::fmt;
-use crate::{HashEngine, Hmac, HmacEngine, IsByteArray};
+use crate::{Hash, HashEngine, Hmac, HmacEngine};
#[rustfmt::skip] // Keep public re-exports separate.
#[doc(no_inline)]
@@ -67,14 +67,14 @@ where
/// (255 * hash output length).
pub fn expand(&self, info: &[u8], okm: &mut [u8]) -> Result<(), MaxLengthError> {
// Length of output keying material in bytes must be less than 255 * hash length.
- if okm.len() > (MAX_OUTPUT_BLOCKS * T::Bytes::LEN) {
- return Err(MaxLengthError { max: MAX_OUTPUT_BLOCKS * T::Bytes::LEN });
+ if okm.len() > (MAX_OUTPUT_BLOCKS * T::Hash::LEN) {
+ return Err(MaxLengthError { max: MAX_OUTPUT_BLOCKS * T::Hash::LEN });
}
// Counter starts at "1" based on RFC5869 spec and is committed to in the hash.
let mut counter = 1u8;
// Ceiling calculation for the total number of blocks (iterations) required for the expand.
- let total_blocks = okm.len().div_ceil(T::Bytes::LEN);
+ let total_blocks = okm.len().div_ceil(T::Hash::LEN);
while counter <= total_blocks as u8 {
let mut engine: HmacEngine<T> = HmacEngine::new(self.prk.as_ref());
@@ -82,20 +82,20 @@ where
// 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;
+ let previous_start_index = (counter as usize - 2) * T::Hash::LEN;
+ let previous_end_index = (counter as usize - 1) * T::Hash::LEN;
engine.input(&okm[previous_start_index..previous_end_index]);
}
engine.input(info);
engine.input(&[counter]);
let t = engine.finalize();
- let start_index = (counter as usize - 1) * T::Bytes::LEN;
+ let start_index = (counter as usize - 1) * T::Hash::LEN;
// Last block might not take full hash length.
let end_index = if counter == (total_blocks as u8) {
okm.len()
} else {
- counter as usize * T::Bytes::LEN
+ counter as usize * T::Hash::LEN
};
okm[start_index..end_index].copy_from_slice(&t.as_ref()[0..(end_index - start_index)]);
diff --git a/hashes/src/hmac/mod.rs b/hashes/src/hmac/mod.rs
index ffeefb03..01effd24 100644
--- a/hashes/src/hmac/mod.rs
+++ b/hashes/src/hmac/mod.rs
@@ -145,7 +145,6 @@ impl<T: HashEngine> HmacEngine<T> {
impl<T: HashEngine> HashEngine for HmacEngine<T> {
type Hash = Hmac<T::Hash>;
- type Bytes = T::Bytes;
const BLOCK_SIZE: usize = T::BLOCK_SIZE;
fn n_bytes_hashed(&self) -> u64 { self.iengine.n_bytes_hashed() }
diff --git a/hashes/src/lib.rs b/hashes/src/lib.rs
index 7671ce27..037f5224 100644
--- a/hashes/src/lib.rs
+++ b/hashes/src/lib.rs
@@ -175,12 +175,6 @@ pub trait HashEngine: Clone {
/// The `Hash` type returned when finalizing this engine.
type Hash: Hash;
- /// The byte array that is used internally in [`HashEngine::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 5af0a8ea..72139c88 100644
--- a/hashes/src/ripemd160/mod.rs
+++ b/hashes/src/ripemd160/mod.rs
@@ -91,7 +91,6 @@ 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 8fb8a908..147511fd 100644
--- a/hashes/src/sha1/mod.rs
+++ b/hashes/src/sha1/mod.rs
@@ -82,7 +82,6 @@ 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 75c7f29f..bc736446 100644
--- a/hashes/src/sha256/mod.rs
+++ b/hashes/src/sha256/mod.rs
@@ -166,7 +166,6 @@ 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 8d864a9b..0db4cb91 100644
--- a/hashes/src/sha256d/mod.rs
+++ b/hashes/src/sha256d/mod.rs
@@ -47,7 +47,6 @@ 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 f32ea591..45848e06 100644
--- a/hashes/src/sha256t/mod.rs
+++ b/hashes/src/sha256t/mod.rs
@@ -145,7 +145,6 @@ impl<T: Tag> Clone for HashEngine<T> {
impl<T: Tag> crate::HashEngine for HashEngine<T> {
type Hash = Hash<T>;
- 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 712f1bf1..d87bde5d 100644
--- a/hashes/src/sha384/mod.rs
+++ b/hashes/src/sha384/mod.rs
@@ -35,7 +35,6 @@ 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/sha3_256/mod.rs b/hashes/src/sha3_256/mod.rs
index 17ca3815..6e9c841c 100644
--- a/hashes/src/sha3_256/mod.rs
+++ b/hashes/src/sha3_256/mod.rs
@@ -212,7 +212,6 @@ impl HashEngine {
impl crate::HashEngine for HashEngine {
type Hash = Hash;
- type Bytes = [u8; 32];
const BLOCK_SIZE: usize = RATE;
crate::internal_macros::engine_input_impl!();
diff --git a/hashes/src/sha512/mod.rs b/hashes/src/sha512/mod.rs
index 0d1b77c5..7c8677ad 100644
--- a/hashes/src/sha512/mod.rs
+++ b/hashes/src/sha512/mod.rs
@@ -124,7 +124,6 @@ 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 fc70cfee..5cae9c8c 100644
--- a/hashes/src/sha512_256/mod.rs
+++ b/hashes/src/sha512_256/mod.rs
@@ -48,7 +48,6 @@ 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 4ad9bdfd..47d1fb04 100644
--- a/hashes/src/siphash24/mod.rs
+++ b/hashes/src/siphash24/mod.rs
@@ -168,7 +168,6 @@ impl HashEngine {
impl crate::HashEngine for HashEngine {
type Hash = Hash;
- type Bytes = [u8; 8];
const BLOCK_SIZE: usize = 8;
#[inline]
Why this scored 18/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.