hashes: include midstate and buffer in MidstateError
What changed, and why it matters
This change enriches an error type in the SHA-256 hashing code. When a caller asks for the internal 'midstate' snapshot at a non-aligned point, the error now also returns the nearest aligned snapshot and any leftover bytes, so the caller can resume hashing later. It is a feature/API improvement, not a fix for an active security flaw.
No security action required; review as a normal API change. If consumed downstream, verify that callers do not accidentally rely on the new fields for security-critical decisions without checking alignment themselves.
Security signals we found
No memory-safety bug signals: the diff uses existing Rust slice indexing with a length derived from the same buffer
No secret-exposure signals: the returned midstate and buffer are exactly what the caller already supplied/hashed
No authentication-bypass or integrity-break signals
Error-type expansion is API-facing, not a vulnerability patch
Evidence from the diff
The commit modifies MidstateError in hashes/src/sha256/mod.rs to carry block_aligned_midstate, unprocessed_bytes, and unprocessed_bytes_len. It adds constructors (midstate(), unprocessed_bytes()) so callers can recover from a non-block-aligned midstate extraction and continue hashing. The underlying midstate() logic still rejects non-aligned extractions; it just provides more data in the rejection. No cryptographic operations, bounds checks, or secret-handling paths were changed in a security-sensitive way.
Changed components
hashes/src/sha256/mod.rsMidstateError structHashEngine::midstate() error pathInspect captured patch +25 / −1
diff --git a/hashes/src/sha256/mod.rs b/hashes/src/sha256/mod.rs
index e0fe318d..6d18d141 100644
--- a/hashes/src/sha256/mod.rs
+++ b/hashes/src/sha256/mod.rs
@@ -69,7 +69,20 @@ impl HashEngine {
/// Please see docs on [`Midstate`] before using this function.
pub fn midstate(&self) -> Result<Midstate, MidstateError> {
if !self.can_extract_midstate() {
- return Err(MidstateError { invalid_n_bytes_hashed: self.bytes_hashed });
+ let unprocessed_len = (self.bytes_hashed % BLOCK_SIZE as u64) as usize;
+ let aligned_bytes = self.bytes_hashed - unprocessed_len as u64;
+
+ let mut midstate_bytes = [0; 32];
+ for (val, ret_bytes) in self.h.iter().zip(midstate_bytes.bitcoin_as_chunks_mut::<4>().0) {
+ *ret_bytes = val.to_be_bytes();
+ }
+
+ return Err(MidstateError {
+ invalid_n_bytes_hashed: self.bytes_hashed,
+ block_aligned_midstate: Midstate { bytes: midstate_bytes, bytes_hashed: aligned_bytes },
+ unprocessed_bytes: self.buffer,
+ unprocessed_bytes_len: unprocessed_len
+ });
}
Ok(self.midstate_unchecked())
}
@@ -241,6 +254,17 @@ impl convert::AsRef<[u8]> for Midstate {
pub struct MidstateError {
/// The invalid number of bytes hashed.
invalid_n_bytes_hashed: u64,
+ block_aligned_midstate: Midstate,
+ unprocessed_bytes: [u8; BLOCK_SIZE],
+ unprocessed_bytes_len: usize,
+}
+
+impl MidstateError {
+ /// Returns block-aligned midstate
+ pub const fn midstate(&self) -> &Midstate { &self.block_aligned_midstate }
+
+ /// returns the unprocessed bytes remaining in the buffer.
+ pub fn unprocessed_bytes(&self) -> &[u8] { &self.unprocessed_bytes[..self.unprocessed_bytes_len] }
}
impl fmt::Display for MidstateError {
Why this scored 19/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.