hashes: add sha256::Midstate::SHA256_IV constant
What changed, and why it matters
This commit is a routine internal refactoring in the rust-bitcoin SHA-256 hashing code. It exposes the SHA-256 initial value (IV) as a public constant and renames an internal helper function so it can start from any midstate rather than always starting fresh. There is no security bug or fix here—just a code cleanup and API preparation for future const-context hashing features.
No security action required. Review as normal code-quality/API change.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change adds Midstate::SHA256_IV, a public const representing the SHA-256 initial state, and renames compute_midstate_unoptimized to update_midstate_unoptimized, making it a method on Midstate that starts from self instead of hard-coding the IV. It also accumulates bytes_hashed correctly across calls. A unit test verifies the new constant matches HashEngine::new().midstate(). This is purely a refactor/enhancement; no vulnerability is introduced or patched.
Changed components
hashes/src/sha256/crypto/mod.rshashes/src/sha256/mod.rshashes/src/sha256/tests.rsInspect captured patch +39 / −14
diff --git a/hashes/src/sha256/crypto/mod.rs b/hashes/src/sha256/crypto/mod.rs
index 9348321a..e339a40e 100644
--- a/hashes/src/sha256/crypto/mod.rs
+++ b/hashes/src/sha256/crypto/mod.rs
@@ -149,17 +149,21 @@ impl Midstate {
w
}
- pub(super) const fn compute_midstate_unoptimized(bytes: &[u8], finalize: bool) -> Self {
- let mut state = [
- 0x6a09e667u32,
- 0xbb67ae85,
- 0x3c6ef372,
- 0xa54ff53a,
- 0x510e527f,
- 0x9b05688c,
- 0x1f83d9ab,
- 0x5be0cd19,
- ];
+ #[rustfmt::skip]
+ const fn bytes_to_state(&self) -> [u32; 8] {
+ const fn be_bytes_to_u32(bytes: &[u8], offs: usize) -> u32 {
+ u32::from_be_bytes([bytes[offs], bytes[offs + 1], bytes[offs + 2], bytes[offs + 3]])
+ }
+ [
+ be_bytes_to_u32(&self.bytes, 0), be_bytes_to_u32(&self.bytes, 4),
+ be_bytes_to_u32(&self.bytes, 8), be_bytes_to_u32(&self.bytes, 12),
+ be_bytes_to_u32(&self.bytes, 16), be_bytes_to_u32(&self.bytes, 20),
+ be_bytes_to_u32(&self.bytes, 24), be_bytes_to_u32(&self.bytes, 28),
+ ]
+ }
+
+ pub(super) const fn update_midstate_unoptimized(self, bytes: &[u8], finalize: bool) -> Self {
+ let mut state = self.bytes_to_state();
let num_chunks = (bytes.len() + 9).div_ceil(64);
let mut chunk = 0;
@@ -294,7 +298,7 @@ impl Midstate {
output[i * 4 + 3] = (state[i + 0] >> 0) as u8;
i += 1;
}
- Self { bytes: output, bytes_hashed: bytes.len() as u64 }
+ Self { bytes: output, bytes_hashed: self.bytes_hashed + bytes.len() as u64 }
}
}
diff --git a/hashes/src/sha256/mod.rs b/hashes/src/sha256/mod.rs
index 9b27a447..e57f5b45 100644
--- a/hashes/src/sha256/mod.rs
+++ b/hashes/src/sha256/mod.rs
@@ -70,7 +70,7 @@ impl Hash {
///
/// Warning: this function is inefficient. It should be only used in `const` context.
pub const fn hash_unoptimized(bytes: &[u8]) -> Self {
- Self(Midstate::compute_midstate_unoptimized(bytes, true).bytes)
+ Self(Midstate::SHA256_IV.update_midstate_unoptimized(bytes, true).bytes)
}
}
@@ -197,6 +197,20 @@ pub struct Midstate {
}
impl Midstate {
+ /// The midstate obtained by creating a new hash engine and immediately extracting its midstate.
+ #[rustfmt::skip]
+ pub const SHA256_IV: Self = Self {
+ // You can visually verify this value by just squishing the groups of 4 bytes together into
+ // u32s then comparing the result to the first line of HashEngine::new.
+ bytes: [
+ 0x6a, 0x09, 0xe6, 0x67, 0xbb, 0x67, 0xae, 0x85,
+ 0x3c, 0x6e, 0xf3, 0x72, 0xa5, 0x4f, 0xf5, 0x3a,
+ 0x51, 0x0e, 0x52, 0x7f, 0x9b, 0x05, 0x68, 0x8c,
+ 0x1f, 0x83, 0xd9, 0xab, 0x5b, 0xe0, 0xcd, 0x19,
+ ],
+ bytes_hashed: 0,
+ };
+
/// Constructs a new [`Midstate`] from the `state` and the `bytes_hashed` to get to that state.
///
/// # Panics
@@ -240,7 +254,7 @@ impl Midstate {
buf[i] = hash.0[i % hash.0.len()];
i += 1;
}
- Self::compute_midstate_unoptimized(&buf, false)
+ Self::SHA256_IV.update_midstate_unoptimized(&buf, false)
}
}
diff --git a/hashes/src/sha256/tests.rs b/hashes/src/sha256/tests.rs
index 961b827b..d56251ce 100644
--- a/hashes/src/sha256/tests.rs
+++ b/hashes/src/sha256/tests.rs
@@ -243,3 +243,10 @@ mod wasm_tests {
engine_with_state();
}
}
+
+#[test]
+fn initial_midstate() {
+ let mid1 = Midstate::SHA256_IV;
+ let mid2 = super::HashEngine::new().midstate().unwrap();
+ assert_eq!(mid1, mid2);
+}
Why this scored 15/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.