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: ACKcbfddb0394
successfully ran local tests Tree-SHA512: a9d932938afcbd6dfb9db471a02fa7e3fff8f0659906627001ad241390b9af57088fd34afeae551c70c2c49783e6296f110b57ff9de6fed2609f4648ec8fd934
This commit is contained in:
commit
76ea4eb400
|
@ -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 {
|
||||||
|
|
|
@ -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) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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!();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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!();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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!();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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..];
|
||||||
|
|
Loading…
Reference in New Issue