Merge rust-bitcoin/rust-bitcoin#3298: hashes: Rename length field and use u64

cbfddb0394 hashes: Rename length field and use u64 (Tobin C. Harding)

Pull request description:

  The hash engine types have a `length` field that is used to cache the number of bytes hashed so far, as such it is an arbitrary number and could use a `u64` instead of `usize`.

  While we are at it rename `length` to `bytes_hashed` to remove any ambiguity of what this field is. Note this field is private, we already have the public getter `n_bytes_hashes` to get the value.

  Introduce a private function `incomplete_block_size`, the purpose of this function is to put all the casts in one place so they can be well documented and easily understood.

  Fix: #3016

ACKs for top commit:
  apoelstra:
    ACK cbfddb0394 successfully ran local tests

Tree-SHA512: a9d932938afcbd6dfb9db471a02fa7e3fff8f0659906627001ad241390b9af57088fd34afeae551c70c2c49783e6296f110b57ff9de6fed2609f4648ec8fd934
This commit is contained in:
merge-script 2024-09-23 20:10:09 +00:00
commit 76ea4eb400
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
12 changed files with 86 additions and 78 deletions

View File

@ -34,7 +34,7 @@ impl Default for HashEngine {
impl crate::HashEngine for HashEngine { impl crate::HashEngine for HashEngine {
const BLOCK_SIZE: usize = 64; // Same as sha256::HashEngine::BLOCK_SIZE; const BLOCK_SIZE: usize = 64; // Same as sha256::HashEngine::BLOCK_SIZE;
fn input(&mut self, data: &[u8]) { self.0.input(data) } fn input(&mut self, data: &[u8]) { self.0.input(data) }
fn n_bytes_hashed(&self) -> usize { self.0.n_bytes_hashed() } fn n_bytes_hashed(&self) -> u64 { self.0.n_bytes_hashed() }
} }
fn from_engine(e: HashEngine) -> Hash { fn from_engine(e: HashEngine) -> Hash {

View File

@ -102,7 +102,7 @@ impl<T: GeneralHash> HmacEngine<T> {
impl<T: GeneralHash> HashEngine for HmacEngine<T> { impl<T: GeneralHash> HashEngine for HmacEngine<T> {
const BLOCK_SIZE: usize = T::Engine::BLOCK_SIZE; const BLOCK_SIZE: usize = T::Engine::BLOCK_SIZE;
fn n_bytes_hashed(&self) -> usize { self.iengine.n_bytes_hashed() } fn n_bytes_hashed(&self) -> u64 { self.iengine.n_bytes_hashed() }
fn input(&mut self, buf: &[u8]) { self.iengine.input(buf) } fn input(&mut self, buf: &[u8]) { self.iengine.input(buf) }
} }

View File

@ -182,8 +182,8 @@ pub trait HashEngine: Clone {
/// Add data to the hash engine. /// Add data to the hash engine.
fn input(&mut self, data: &[u8]); fn input(&mut self, data: &[u8]);
/// Return the number of bytes already n_bytes_hashed(inputted). /// Return the number of bytes already input into the engine.
fn n_bytes_hashed(&self) -> usize; fn n_bytes_hashed(&self) -> u64;
} }
/// Trait describing hash digests which can be constructed by hashing arbitrary data. /// Trait describing hash digests which can be constructed by hashing arbitrary data.
@ -309,6 +309,13 @@ mod sealed {
impl<const N: usize> IsByteArray for [u8; N] {} impl<const N: usize> IsByteArray for [u8; N] {}
} }
fn incomplete_block_len<H: HashEngine>(eng: &H) -> usize {
let block_size = <H as HashEngine>::BLOCK_SIZE as u64; // Cast usize to u64 is ok.
// After modulo operation we know cast u64 to usize as ok.
(eng.n_bytes_hashed() % block_size) as usize
}
/// Attempted to create a hash from an invalid length slice. /// Attempted to create a hash from an invalid length slice.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct FromSliceError { pub struct FromSliceError {

View File

@ -6,7 +6,7 @@ use core::cmp;
use core::ops::Index; use core::ops::Index;
use core::slice::SliceIndex; use core::slice::SliceIndex;
use crate::HashEngine as _; use crate::{incomplete_block_len, HashEngine as _};
crate::internal_macros::hash_type! { crate::internal_macros::hash_type! {
160, 160,
@ -17,19 +17,19 @@ crate::internal_macros::hash_type! {
#[cfg(not(hashes_fuzz))] #[cfg(not(hashes_fuzz))]
fn from_engine(mut e: HashEngine) -> Hash { fn from_engine(mut e: HashEngine) -> Hash {
// pad buffer with a single 1-bit then all 0s, until there are exactly 8 bytes remaining // pad buffer with a single 1-bit then all 0s, until there are exactly 8 bytes remaining
let data_len = e.length as u64; let n_bytes_hashed = e.bytes_hashed;
let zeroes = [0; BLOCK_SIZE - 8]; let zeroes = [0; BLOCK_SIZE - 8];
e.input(&[0x80]); e.input(&[0x80]);
if e.length % BLOCK_SIZE > zeroes.len() { if crate::incomplete_block_len(&e) > zeroes.len() {
e.input(&zeroes); e.input(&zeroes);
} }
let pad_length = zeroes.len() - (e.length % BLOCK_SIZE); let pad_length = zeroes.len() - incomplete_block_len(&e);
e.input(&zeroes[..pad_length]); e.input(&zeroes[..pad_length]);
debug_assert_eq!(e.length % BLOCK_SIZE, zeroes.len()); debug_assert_eq!(incomplete_block_len(&e), zeroes.len());
e.input(&(8 * data_len).to_le_bytes()); e.input(&(8 * n_bytes_hashed).to_le_bytes());
debug_assert_eq!(e.length % BLOCK_SIZE, 0); debug_assert_eq!(incomplete_block_len(&e), 0);
Hash(e.midstate()) Hash(e.midstate())
} }
@ -48,7 +48,7 @@ const BLOCK_SIZE: usize = 64;
pub struct HashEngine { pub struct HashEngine {
buffer: [u8; BLOCK_SIZE], buffer: [u8; BLOCK_SIZE],
h: [u32; 5], h: [u32; 5],
length: usize, bytes_hashed: u64,
} }
impl HashEngine { impl HashEngine {
@ -56,7 +56,7 @@ impl HashEngine {
pub const fn new() -> Self { pub const fn new() -> Self {
Self { Self {
h: [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0], h: [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0],
length: 0, bytes_hashed: 0,
buffer: [0; BLOCK_SIZE], buffer: [0; BLOCK_SIZE],
} }
} }
@ -85,7 +85,7 @@ impl Default for HashEngine {
impl crate::HashEngine for HashEngine { impl crate::HashEngine for HashEngine {
const BLOCK_SIZE: usize = 64; const BLOCK_SIZE: usize = 64;
fn n_bytes_hashed(&self) -> usize { self.length } fn n_bytes_hashed(&self) -> u64 { self.bytes_hashed }
engine_input_impl!(); engine_input_impl!();
} }

View File

@ -6,7 +6,7 @@ use core::cmp;
use core::ops::Index; use core::ops::Index;
use core::slice::SliceIndex; use core::slice::SliceIndex;
use crate::HashEngine as _; use crate::{incomplete_block_len, HashEngine as _};
crate::internal_macros::hash_type! { crate::internal_macros::hash_type! {
160, 160,
@ -16,19 +16,19 @@ crate::internal_macros::hash_type! {
fn from_engine(mut e: HashEngine) -> Hash { fn from_engine(mut e: HashEngine) -> Hash {
// pad buffer with a single 1-bit then all 0s, until there are exactly 8 bytes remaining // pad buffer with a single 1-bit then all 0s, until there are exactly 8 bytes remaining
let data_len = e.length as u64; let n_bytes_hashed = e.bytes_hashed;
let zeroes = [0; BLOCK_SIZE - 8]; let zeroes = [0; BLOCK_SIZE - 8];
e.input(&[0x80]); e.input(&[0x80]);
if e.length % BLOCK_SIZE > zeroes.len() { if incomplete_block_len(&e) > zeroes.len() {
e.input(&zeroes); e.input(&zeroes);
} }
let pad_length = zeroes.len() - (e.length % BLOCK_SIZE); let pad_length = zeroes.len() - incomplete_block_len(&e);
e.input(&zeroes[..pad_length]); e.input(&zeroes[..pad_length]);
debug_assert_eq!(e.length % BLOCK_SIZE, zeroes.len()); debug_assert_eq!(incomplete_block_len(&e), zeroes.len());
e.input(&(8 * data_len).to_be_bytes()); e.input(&(8 * n_bytes_hashed).to_be_bytes());
debug_assert_eq!(e.length % BLOCK_SIZE, 0); debug_assert_eq!(incomplete_block_len(&e), 0);
Hash(e.midstate()) Hash(e.midstate())
} }
@ -40,7 +40,7 @@ const BLOCK_SIZE: usize = 64;
pub struct HashEngine { pub struct HashEngine {
buffer: [u8; BLOCK_SIZE], buffer: [u8; BLOCK_SIZE],
h: [u32; 5], h: [u32; 5],
length: usize, bytes_hashed: u64,
} }
impl HashEngine { impl HashEngine {
@ -48,7 +48,7 @@ impl HashEngine {
pub const fn new() -> Self { pub const fn new() -> Self {
Self { Self {
h: [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0], h: [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0],
length: 0, bytes_hashed: 0,
buffer: [0; BLOCK_SIZE], buffer: [0; BLOCK_SIZE],
} }
} }
@ -77,7 +77,7 @@ impl Default for HashEngine {
impl crate::HashEngine for HashEngine { impl crate::HashEngine for HashEngine {
const BLOCK_SIZE: usize = 64; const BLOCK_SIZE: usize = 64;
fn n_bytes_hashed(&self) -> usize { self.length } fn n_bytes_hashed(&self) -> u64 { self.bytes_hashed }
engine_input_impl!(); engine_input_impl!();
} }

View File

@ -12,7 +12,7 @@ use core::{cmp, convert, fmt};
use hex::DisplayHex; use hex::DisplayHex;
use crate::{sha256d, HashEngine as _}; use crate::{incomplete_block_len, sha256d, HashEngine as _};
#[cfg(doc)] #[cfg(doc)]
use crate::{sha256t, sha256t_tag}; use crate::{sha256t, sha256t_tag};
@ -25,19 +25,19 @@ crate::internal_macros::hash_type! {
#[cfg(not(hashes_fuzz))] #[cfg(not(hashes_fuzz))]
fn from_engine(mut e: HashEngine) -> Hash { fn from_engine(mut e: HashEngine) -> Hash {
// pad buffer with a single 1-bit then all 0s, until there are exactly 8 bytes remaining // pad buffer with a single 1-bit then all 0s, until there are exactly 8 bytes remaining
let data_len = e.length as u64; let n_bytes_hashed = e.bytes_hashed;
let zeroes = [0; BLOCK_SIZE - 8]; let zeroes = [0; BLOCK_SIZE - 8];
e.input(&[0x80]); e.input(&[0x80]);
if e.length % BLOCK_SIZE > zeroes.len() { if incomplete_block_len(&e) > zeroes.len() {
e.input(&zeroes); e.input(&zeroes);
} }
let pad_length = zeroes.len() - (e.length % BLOCK_SIZE); let pad_length = zeroes.len() - incomplete_block_len(&e);
e.input(&zeroes[..pad_length]); e.input(&zeroes[..pad_length]);
debug_assert_eq!(e.length % BLOCK_SIZE, zeroes.len()); debug_assert_eq!(incomplete_block_len(&e), zeroes.len());
e.input(&(8 * data_len).to_be_bytes()); e.input(&(8 * n_bytes_hashed).to_be_bytes());
debug_assert_eq!(e.length % BLOCK_SIZE, 0); debug_assert_eq!(incomplete_block_len(&e), 0);
Hash(e.midstate_unchecked().bytes) Hash(e.midstate_unchecked().bytes)
} }
@ -60,7 +60,7 @@ const BLOCK_SIZE: usize = 64;
pub struct HashEngine { pub struct HashEngine {
buffer: [u8; BLOCK_SIZE], buffer: [u8; BLOCK_SIZE],
h: [u32; 8], h: [u32; 8],
length: usize, bytes_hashed: u64,
} }
impl HashEngine { impl HashEngine {
@ -71,7 +71,7 @@ impl HashEngine {
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab,
0x5be0cd19, 0x5be0cd19,
], ],
length: 0, bytes_hashed: 0,
buffer: [0; BLOCK_SIZE], buffer: [0; BLOCK_SIZE],
} }
} }
@ -85,7 +85,7 @@ impl HashEngine {
*ret_val = u32::from_be_bytes(midstate_bytes.try_into().expect("4 byte slice")); *ret_val = u32::from_be_bytes(midstate_bytes.try_into().expect("4 byte slice"));
} }
HashEngine { buffer: [0; BLOCK_SIZE], h: ret, length: midstate.length } HashEngine { buffer: [0; BLOCK_SIZE], h: ret, bytes_hashed: midstate.bytes_hashed }
} }
/// Returns `true` if the midstate can be extracted from this engine. /// Returns `true` if the midstate can be extracted from this engine.
@ -94,14 +94,14 @@ impl HashEngine {
/// the hash engine is a multiple of 64. See caveat on [`Self::midstate`]. /// the hash engine is a multiple of 64. See caveat on [`Self::midstate`].
/// ///
/// Please see docs on [`Midstate`] before using this function. /// Please see docs on [`Midstate`] before using this function.
pub const fn can_extract_midstate(&self) -> bool { self.length % 64 == 0 } pub const fn can_extract_midstate(&self) -> bool { self.bytes_hashed % 64 == 0 }
/// Outputs the midstate of the hash engine. /// Outputs the midstate of the hash engine.
/// ///
/// Please see docs on [`Midstate`] before using this function. /// Please see docs on [`Midstate`] before using this function.
pub fn midstate(&self) -> Result<Midstate, MidstateError> { pub fn midstate(&self) -> Result<Midstate, MidstateError> {
if !self.can_extract_midstate() { if !self.can_extract_midstate() {
return Err(MidstateError { invalid_length: self.length }); return Err(MidstateError { invalid_n_bytes_hashed: self.bytes_hashed });
} }
Ok(self.midstate_unchecked()) Ok(self.midstate_unchecked())
} }
@ -113,7 +113,7 @@ impl HashEngine {
for (val, ret_bytes) in self.h.iter().zip(ret.chunks_exact_mut(4)) { for (val, ret_bytes) in self.h.iter().zip(ret.chunks_exact_mut(4)) {
ret_bytes.copy_from_slice(&val.to_be_bytes()); ret_bytes.copy_from_slice(&val.to_be_bytes());
} }
Midstate { bytes: ret, length: self.length } Midstate { bytes: ret, bytes_hashed: self.bytes_hashed }
} }
// Does not check that `HashEngine::can_extract_midstate`. // Does not check that `HashEngine::can_extract_midstate`.
@ -121,7 +121,7 @@ impl HashEngine {
fn midstate_unchecked(&self) -> Midstate { fn midstate_unchecked(&self) -> Midstate {
let mut ret = [0; 32]; let mut ret = [0; 32];
ret.copy_from_slice(&self.buffer[..32]); ret.copy_from_slice(&self.buffer[..32]);
Midstate { bytes: ret, length: self.length } Midstate { bytes: ret, bytes_hashed: self.bytes_hashed }
} }
} }
@ -132,7 +132,7 @@ impl Default for HashEngine {
impl crate::HashEngine for HashEngine { impl crate::HashEngine for HashEngine {
const BLOCK_SIZE: usize = 64; const BLOCK_SIZE: usize = 64;
fn n_bytes_hashed(&self) -> usize { self.length } fn n_bytes_hashed(&self) -> u64 { self.bytes_hashed }
engine_input_impl!(); engine_input_impl!();
} }
@ -177,7 +177,7 @@ pub struct Midstate {
bytes: [u8; 32], bytes: [u8; 32],
/// Number of bytes hashed to achieve this midstate. /// Number of bytes hashed to achieve this midstate.
// INVARIANT must always be a multiple of 64. // INVARIANT must always be a multiple of 64.
length: usize, bytes_hashed: u64,
} }
impl Midstate { impl Midstate {
@ -186,19 +186,19 @@ impl Midstate {
/// # Panics /// # Panics
/// ///
/// Panics if `bytes_hashed` is not a multiple of 64. /// Panics if `bytes_hashed` is not a multiple of 64.
pub const fn new(state: [u8; 32], bytes_hashed: usize) -> Self { pub const fn new(state: [u8; 32], bytes_hashed: u64) -> Self {
if bytes_hashed % 64 != 0 { if bytes_hashed % 64 != 0 {
panic!("bytes hashed is not a multiple of 64"); panic!("bytes hashed is not a multiple of 64");
} }
Midstate { bytes: state, length: bytes_hashed } Midstate { bytes: state, bytes_hashed }
} }
/// Deconstructs the [`Midstate`], returning the underlying byte array and number of bytes hashed. /// Deconstructs the [`Midstate`], returning the underlying byte array and number of bytes hashed.
pub const fn as_parts(&self) -> (&[u8; 32], usize) { (&self.bytes, self.length) } pub const fn as_parts(&self) -> (&[u8; 32], u64) { (&self.bytes, self.bytes_hashed) }
/// Deconstructs the [`Midstate`], returning the underlying byte array and number of bytes hashed. /// Deconstructs the [`Midstate`], returning the underlying byte array and number of bytes hashed.
pub const fn into_parts(self) -> ([u8; 32], usize) { (self.bytes, self.length) } pub const fn into_parts(self) -> ([u8; 32], u64) { (self.bytes, self.bytes_hashed) }
/// Creates midstate for tagged hashes. /// Creates midstate for tagged hashes.
/// ///
@ -222,7 +222,7 @@ impl fmt::Debug for Midstate {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Midstate") f.debug_struct("Midstate")
.field("bytes", &self.bytes.as_hex()) .field("bytes", &self.bytes.as_hex())
.field("length", &self.length) .field("length", &self.bytes_hashed)
.finish() .finish()
} }
} }
@ -235,7 +235,7 @@ impl convert::AsRef<[u8]> for Midstate {
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct MidstateError { pub struct MidstateError {
/// The invalid number of bytes hashed. /// The invalid number of bytes hashed.
invalid_length: usize, invalid_n_bytes_hashed: u64,
} }
impl fmt::Display for MidstateError { impl fmt::Display for MidstateError {
@ -243,7 +243,7 @@ impl fmt::Display for MidstateError {
write!( write!(
f, f,
"invalid number of bytes hashed {} (should have been a multiple of 64)", "invalid number of bytes hashed {} (should have been a multiple of 64)",
self.invalid_length self.invalid_n_bytes_hashed
) )
} }
} }
@ -485,7 +485,7 @@ impl Midstate {
output[i * 4 + 3] = (state[i + 0] >> 0) as u8; output[i * 4 + 3] = (state[i + 0] >> 0) as u8;
i += 1; i += 1;
} }
Midstate { bytes: output, length: bytes.len() } Midstate { bytes: output, bytes_hashed: bytes.len() as u64 }
} }
} }
@ -996,7 +996,7 @@ mod tests {
let mut midstate_engine = let mut midstate_engine =
sha256::HashEngine::from_midstate(engine.midstate_unchecked()); sha256::HashEngine::from_midstate(engine.midstate_unchecked());
assert_eq!(engine.h, midstate_engine.h); assert_eq!(engine.h, midstate_engine.h);
assert_eq!(engine.length, midstate_engine.length); assert_eq!(engine.bytes_hashed, midstate_engine.bytes_hashed);
engine.input(data); engine.input(data);
midstate_engine.input(data); midstate_engine.input(data);
assert_eq!(engine.h, midstate_engine.h); assert_eq!(engine.h, midstate_engine.h);
@ -1037,7 +1037,7 @@ mod tests {
assert_eq!( assert_eq!(
Hash::hash(bytes), Hash::hash(bytes),
Hash::hash_unoptimized(bytes), Hash::hash_unoptimized(bytes),
"hashes don't match for length {}", "hashes don't match for n_bytes_hashed {}",
i + 1 i + 1
); );
} }

View File

@ -29,7 +29,7 @@ impl Default for HashEngine {
impl crate::HashEngine for HashEngine { impl crate::HashEngine for HashEngine {
const BLOCK_SIZE: usize = 64; // Same as sha256::HashEngine::BLOCK_SIZE; const BLOCK_SIZE: usize = 64; // Same as sha256::HashEngine::BLOCK_SIZE;
fn input(&mut self, data: &[u8]) { self.0.input(data) } fn input(&mut self, data: &[u8]) { self.0.input(data) }
fn n_bytes_hashed(&self) -> usize { self.0.n_bytes_hashed() } fn n_bytes_hashed(&self) -> u64 { self.0.n_bytes_hashed() }
} }
fn from_engine(e: HashEngine) -> Hash { fn from_engine(e: HashEngine) -> Hash {

View File

@ -35,7 +35,7 @@ impl Default for HashEngine {
impl crate::HashEngine for HashEngine { impl crate::HashEngine for HashEngine {
const BLOCK_SIZE: usize = sha512::BLOCK_SIZE; const BLOCK_SIZE: usize = sha512::BLOCK_SIZE;
fn n_bytes_hashed(&self) -> usize { self.0.n_bytes_hashed() } fn n_bytes_hashed(&self) -> u64 { self.0.n_bytes_hashed() }
fn input(&mut self, inp: &[u8]) { self.0.input(inp); } fn input(&mut self, inp: &[u8]) { self.0.input(inp); }
} }

View File

@ -6,7 +6,7 @@ use core::cmp;
use core::ops::Index; use core::ops::Index;
use core::slice::SliceIndex; use core::slice::SliceIndex;
use crate::HashEngine as _; use crate::{incomplete_block_len, HashEngine as _};
crate::internal_macros::hash_type! { crate::internal_macros::hash_type! {
512, 512,
@ -17,20 +17,20 @@ crate::internal_macros::hash_type! {
#[cfg(not(hashes_fuzz))] #[cfg(not(hashes_fuzz))]
pub(crate) fn from_engine(mut e: HashEngine) -> Hash { pub(crate) fn from_engine(mut e: HashEngine) -> Hash {
// pad buffer with a single 1-bit then all 0s, until there are exactly 16 bytes remaining // pad buffer with a single 1-bit then all 0s, until there are exactly 16 bytes remaining
let data_len = e.length as u64; let n_bytes_hashed = e.bytes_hashed;
let zeroes = [0; BLOCK_SIZE - 16]; let zeroes = [0; BLOCK_SIZE - 16];
e.input(&[0x80]); e.input(&[0x80]);
if e.length % BLOCK_SIZE > zeroes.len() { if incomplete_block_len(&e) > zeroes.len() {
e.input(&zeroes); e.input(&zeroes);
} }
let pad_length = zeroes.len() - (e.length % BLOCK_SIZE); let pad_length = zeroes.len() - incomplete_block_len(&e);
e.input(&zeroes[..pad_length]); e.input(&zeroes[..pad_length]);
debug_assert_eq!(e.length % BLOCK_SIZE, zeroes.len()); debug_assert_eq!(incomplete_block_len(&e), zeroes.len());
e.input(&[0; 8]); e.input(&[0; 8]);
e.input(&(8 * data_len).to_be_bytes()); e.input(&(8 * n_bytes_hashed).to_be_bytes());
debug_assert_eq!(e.length % BLOCK_SIZE, 0); debug_assert_eq!(incomplete_block_len(&e), 0);
Hash(e.midstate()) Hash(e.midstate())
} }
@ -48,7 +48,7 @@ pub(crate) const BLOCK_SIZE: usize = 128;
#[derive(Clone)] #[derive(Clone)]
pub struct HashEngine { pub struct HashEngine {
h: [u64; 8], h: [u64; 8],
length: usize, bytes_hashed: u64,
buffer: [u8; BLOCK_SIZE], buffer: [u8; BLOCK_SIZE],
} }
@ -61,7 +61,7 @@ impl HashEngine {
0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
], ],
length: 0, bytes_hashed: 0,
buffer: [0; BLOCK_SIZE], buffer: [0; BLOCK_SIZE],
} }
} }
@ -96,7 +96,7 @@ impl HashEngine {
0x22312194fc2bf72c, 0x9f555fa3c84c64c2, 0x2393b86b6f53b151, 0x963877195940eabd, 0x22312194fc2bf72c, 0x9f555fa3c84c64c2, 0x2393b86b6f53b151, 0x963877195940eabd,
0x96283ee2a88effe3, 0xbe5e1e2553863992, 0x2b0199fc2c85b8aa, 0x0eb72ddc81c52ca2, 0x96283ee2a88effe3, 0xbe5e1e2553863992, 0x2b0199fc2c85b8aa, 0x0eb72ddc81c52ca2,
], ],
length: 0, bytes_hashed: 0,
buffer: [0; BLOCK_SIZE], buffer: [0; BLOCK_SIZE],
} }
} }
@ -109,7 +109,7 @@ impl HashEngine {
0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939, 0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939,
0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4, 0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4,
], ],
length: 0, bytes_hashed: 0,
buffer: [0; BLOCK_SIZE], buffer: [0; BLOCK_SIZE],
} }
} }
@ -118,7 +118,7 @@ impl HashEngine {
impl crate::HashEngine for HashEngine { impl crate::HashEngine for HashEngine {
const BLOCK_SIZE: usize = 128; const BLOCK_SIZE: usize = 128;
fn n_bytes_hashed(&self) -> usize { self.length } fn n_bytes_hashed(&self) -> u64 { self.bytes_hashed }
engine_input_impl!(); engine_input_impl!();
} }

View File

@ -45,7 +45,7 @@ impl Default for HashEngine {
impl crate::HashEngine for HashEngine { impl crate::HashEngine for HashEngine {
const BLOCK_SIZE: usize = sha512::BLOCK_SIZE; const BLOCK_SIZE: usize = sha512::BLOCK_SIZE;
fn n_bytes_hashed(&self) -> usize { self.0.n_bytes_hashed() } fn n_bytes_hashed(&self) -> u64 { self.0.n_bytes_hashed() }
fn input(&mut self, inp: &[u8]) { self.0.input(inp); } fn input(&mut self, inp: &[u8]) { self.0.input(inp); }
} }

View File

@ -79,7 +79,7 @@ pub struct State {
pub struct HashEngine { pub struct HashEngine {
k0: u64, k0: u64,
k1: u64, k1: u64,
length: usize, // how many bytes we've processed bytes_hashed: u64, // how many bytes we've processed
state: State, // hash State state: State, // hash State
tail: u64, // unprocessed bytes le tail: u64, // unprocessed bytes le
ntail: usize, // how many bytes in tail are valid ntail: usize, // how many bytes in tail are valid
@ -92,7 +92,7 @@ impl HashEngine {
HashEngine { HashEngine {
k0, k0,
k1, k1,
length: 0, bytes_hashed: 0,
state: State { state: State {
v0: k0 ^ 0x736f6d6570736575, v0: k0 ^ 0x736f6d6570736575,
v1: k1 ^ 0x646f72616e646f6d, v1: k1 ^ 0x646f72616e646f6d,
@ -127,16 +127,16 @@ impl crate::HashEngine for HashEngine {
#[inline] #[inline]
fn input(&mut self, msg: &[u8]) { fn input(&mut self, msg: &[u8]) {
let length = msg.len(); let bytes_hashed = msg.len();
self.length += length; self.bytes_hashed += bytes_hashed as u64; // Cast usize to u64 is ok.
let mut needed = 0; let mut needed = 0;
if self.ntail != 0 { if self.ntail != 0 {
needed = 8 - self.ntail; needed = 8 - self.ntail;
self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << (8 * self.ntail); self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(bytes_hashed, needed)) } << (8 * self.ntail);
if length < needed { if bytes_hashed < needed {
self.ntail += length; self.ntail += bytes_hashed;
return; return;
} else { } else {
self.state.v3 ^= self.tail; self.state.v3 ^= self.tail;
@ -147,7 +147,7 @@ impl crate::HashEngine for HashEngine {
} }
// Buffered tail is now flushed, process new input. // Buffered tail is now flushed, process new input.
let len = length - needed; let len = bytes_hashed - needed;
let left = len & 0x7; let left = len & 0x7;
let mut i = needed; let mut i = needed;
@ -165,7 +165,7 @@ impl crate::HashEngine for HashEngine {
self.ntail = left; self.ntail = left;
} }
fn n_bytes_hashed(&self) -> usize { self.length } fn n_bytes_hashed(&self) -> u64 { self.bytes_hashed }
} }
impl Hash { impl Hash {
@ -188,7 +188,7 @@ impl Hash {
pub fn from_engine_to_u64(e: HashEngine) -> u64 { pub fn from_engine_to_u64(e: HashEngine) -> u64 {
let mut state = e.state; let mut state = e.state;
let b: u64 = ((e.length as u64 & 0xff) << 56) | e.tail; let b: u64 = ((e.bytes_hashed & 0xff) << 56) | e.tail;
state.v3 ^= b; state.v3 ^= b;
HashEngine::c_rounds(&mut state); HashEngine::c_rounds(&mut state);

View File

@ -70,15 +70,16 @@ macro_rules! engine_input_impl(
() => ( () => (
#[cfg(not(hashes_fuzz))] #[cfg(not(hashes_fuzz))]
fn input(&mut self, mut inp: &[u8]) { fn input(&mut self, mut inp: &[u8]) {
while !inp.is_empty() { while !inp.is_empty() {
let buf_idx = self.length % <Self as crate::HashEngine>::BLOCK_SIZE; let buf_idx = $crate::incomplete_block_len(self);
let rem_len = <Self as crate::HashEngine>::BLOCK_SIZE - buf_idx; let rem_len = <Self as crate::HashEngine>::BLOCK_SIZE - buf_idx;
let write_len = cmp::min(rem_len, inp.len()); let write_len = cmp::min(rem_len, inp.len());
self.buffer[buf_idx..buf_idx + write_len] self.buffer[buf_idx..buf_idx + write_len]
.copy_from_slice(&inp[..write_len]); .copy_from_slice(&inp[..write_len]);
self.length += write_len; self.bytes_hashed += write_len as u64;
if self.length % <Self as crate::HashEngine>::BLOCK_SIZE == 0 { if $crate::incomplete_block_len(self) == 0 {
self.process_block(); self.process_block();
} }
inp = &inp[write_len..]; inp = &inp[write_len..];