Bound HmacEngine on HashEngine

We would like to do away with the `GeneralHash` trait. Currently we
bound `Hmac` and `HmacEngine` on it but this is unnecessary now that we
have added `HashEngine::finalize` and `HashEngine::Hash`.

Bound the `HmacEngine` on `HashEngine` (which has an associated `Hash`
type returned by `finilalize`).

Bound `Hmac` type on `T::Hash` where `T` is `HashEngine`.

Includes some minor shortening of local variable names around hmac
engine usage.

Note this means that `Hmac` no longer implements `GeneralHash`.
This commit is contained in:
Tobin C. Harding 2025-02-20 13:02:09 +11:00
parent ab63b7a0ff
commit e1bac7da55
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
16 changed files with 117 additions and 121 deletions

View File

@ -10,7 +10,7 @@ use core::ops::Index;
use core::str::FromStr;
use core::{fmt, slice};
use hashes::{hash160, hash_newtype, sha512, GeneralHash, HashEngine, Hmac, HmacEngine};
use hashes::{hash160, hash_newtype, sha512, HashEngine, Hmac, HmacEngine};
use internals::write_err;
use secp256k1::{Secp256k1, XOnlyPublicKey};
@ -584,9 +584,9 @@ impl From<InvalidBase58PayloadLengthError> for Error {
impl Xpriv {
/// Constructs a new master key from a seed value
pub fn new_master(network: impl Into<NetworkKind>, seed: &[u8]) -> Result<Xpriv, Error> {
let mut hmac_engine: HmacEngine<sha512::Hash> = HmacEngine::new(b"Bitcoin seed");
hmac_engine.input(seed);
let hmac_result: Hmac<sha512::Hash> = Hmac::from_engine(hmac_engine);
let mut engine = HmacEngine::<sha512::HashEngine>::new(b"Bitcoin seed");
engine.input(seed);
let hmac = engine.finalize();
Ok(Xpriv {
network: network.into(),
@ -594,9 +594,9 @@ impl Xpriv {
parent_fingerprint: Default::default(),
child_number: ChildNumber::ZERO_NORMAL,
private_key: secp256k1::SecretKey::from_byte_array(
&hmac_result.as_ref()[..32].try_into().expect("Slice should be exactly 32 bytes"),
&hmac.as_ref()[..32].try_into().expect("Slice should be exactly 32 bytes"),
)?,
chain_code: ChainCode::from_hmac(hmac_result),
chain_code: ChainCode::from_hmac(hmac),
})
}
@ -650,25 +650,25 @@ impl Xpriv {
/// Private->Private child key derivation
fn ckd_priv<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>, i: ChildNumber) -> Xpriv {
let mut hmac_engine: HmacEngine<sha512::Hash> = HmacEngine::new(&self.chain_code[..]);
let mut engine = HmacEngine::<sha512::HashEngine>::new(&self.chain_code[..]);
match i {
ChildNumber::Normal { .. } => {
// Non-hardened key: compute public data and use that
hmac_engine.input(
engine.input(
&secp256k1::PublicKey::from_secret_key(secp, &self.private_key).serialize()[..],
);
}
ChildNumber::Hardened { .. } => {
// Hardened key: use only secret data to prevent public derivation
hmac_engine.input(&[0u8]);
hmac_engine.input(&self.private_key[..]);
engine.input(&[0u8]);
engine.input(&self.private_key[..]);
}
}
hmac_engine.input(&u32::from(i).to_be_bytes());
let hmac_result: Hmac<sha512::Hash> = Hmac::from_engine(hmac_engine);
engine.input(&u32::from(i).to_be_bytes());
let hmac: Hmac<sha512::Hash> = engine.finalize();
let sk = secp256k1::SecretKey::from_byte_array(
&hmac_result.as_ref()[..32].try_into().expect("statistically impossible to hit"),
&hmac.as_ref()[..32].try_into().expect("statistically impossible to hit"),
)
.expect("statistically impossible to hit");
let tweaked =
@ -680,7 +680,7 @@ impl Xpriv {
parent_fingerprint: self.fingerprint(secp),
child_number: i,
private_key: tweaked,
chain_code: ChainCode::from_hmac(hmac_result),
chain_code: ChainCode::from_hmac(hmac),
}
}
@ -812,18 +812,15 @@ impl Xpub {
match i {
ChildNumber::Hardened { .. } => Err(Error::CannotDeriveFromHardenedKey),
ChildNumber::Normal { index: n } => {
let mut hmac_engine: HmacEngine<sha512::Hash> =
HmacEngine::new(&self.chain_code[..]);
hmac_engine.input(&self.public_key.serialize()[..]);
hmac_engine.input(&n.to_be_bytes());
let mut engine = HmacEngine::<sha512::HashEngine>::new(&self.chain_code[..]);
engine.input(&self.public_key.serialize()[..]);
engine.input(&n.to_be_bytes());
let hmac_result: Hmac<sha512::Hash> = Hmac::from_engine(hmac_engine);
let hmac = engine.finalize();
let private_key = secp256k1::SecretKey::from_byte_array(
&hmac_result.as_ref()[..32]
.try_into()
.expect("Slice should be exactly 32 bytes"),
&hmac.as_ref()[..32].try_into().expect("Slice should be exactly 32 bytes"),
)?;
let chain_code = ChainCode::from_hmac(hmac_result);
let chain_code = ChainCode::from_hmac(hmac);
Ok((private_key, chain_code))
}
}

View File

@ -39,6 +39,7 @@ 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) }

View File

@ -11,7 +11,7 @@ use alloc::vec;
use alloc::vec::Vec;
use core::fmt;
use crate::{GeneralHash, HashEngine, Hmac, HmacEngine, IsByteArray};
use crate::{HashEngine, Hmac, HmacEngine, IsByteArray};
/// Output keying material max length multiple.
const MAX_OUTPUT_BLOCKS: usize = 255;
@ -33,20 +33,20 @@ impl std::error::Error for MaxLengthError {}
/// HMAC-based Extract-and-Expand Key Derivation Function (HKDF).
#[derive(Copy, Clone)]
pub struct Hkdf<T: GeneralHash> {
pub struct Hkdf<T: HashEngine> {
/// Pseudorandom key based on the extract step.
prk: Hmac<T>,
prk: Hmac<T::Hash>,
}
impl<T: GeneralHash> Hkdf<T>
impl<T: HashEngine> Hkdf<T>
where
<T as GeneralHash>::Engine: Default,
T: Default,
{
/// Initialize a HKDF by performing the extract step.
pub fn new(salt: &[u8], ikm: &[u8]) -> Self {
let mut hmac_engine: HmacEngine<T> = HmacEngine::new(salt);
hmac_engine.input(ikm);
Self { prk: Hmac::from_engine(hmac_engine) }
let mut engine: HmacEngine<T> = HmacEngine::new(salt);
engine.input(ikm);
Self { prk: engine.finalize() }
}
/// Expand the key to generate output key material in okm.
@ -65,19 +65,19 @@ where
let total_blocks = (okm.len() + T::Bytes::LEN - 1) / T::Bytes::LEN;
while counter <= total_blocks as u8 {
let mut hmac_engine: HmacEngine<T> = HmacEngine::new(self.prk.as_ref());
let mut engine: HmacEngine<T> = HmacEngine::new(self.prk.as_ref());
// 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;
hmac_engine.input(&okm[previous_start_index..previous_end_index]);
engine.input(&okm[previous_start_index..previous_end_index]);
}
hmac_engine.input(info);
hmac_engine.input(&[counter]);
engine.input(info);
engine.input(&[counter]);
let t = Hmac::from_engine(hmac_engine);
let t = engine.finalize();
let start_index = (counter as usize - 1) * T::Bytes::LEN;
// Last block might not take full hash length.
let end_index = if counter == (total_blocks as u8) {
@ -106,7 +106,7 @@ where
}
}
impl<T: GeneralHash> fmt::Debug for Hkdf<T> {
impl<T: HashEngine> fmt::Debug for Hkdf<T> {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
use crate::{sha256t, sha256t_tag};
@ -141,7 +141,7 @@ mod tests {
let ikm = Vec::from_hex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap();
let info = Vec::from_hex("f0f1f2f3f4f5f6f7f8f9").unwrap();
let hkdf = Hkdf::<sha256::Hash>::new(&salt, &ikm);
let hkdf = Hkdf::<sha256::HashEngine>::new(&salt, &ikm);
let mut okm = [0u8; 42];
hkdf.expand(&info, &mut okm).unwrap();
@ -163,7 +163,7 @@ mod tests {
"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
).unwrap();
let hkdf = Hkdf::<sha256::Hash>::new(&salt, &ikm);
let hkdf = Hkdf::<sha256::HashEngine>::new(&salt, &ikm);
let mut okm = [0u8; 82];
hkdf.expand(&info, &mut okm).unwrap();
@ -179,7 +179,7 @@ mod tests {
let ikm = Vec::from_hex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap();
let info = Vec::from_hex("f0f1f2f3f4f5f6f7f8f9").unwrap();
let hkdf = Hkdf::<sha256::Hash>::new(&salt, &ikm);
let hkdf = Hkdf::<sha256::HashEngine>::new(&salt, &ikm);
let mut okm = [0u8; 256 * 32];
let e = hkdf.expand(&info, &mut okm);
@ -192,7 +192,7 @@ mod tests {
let ikm = Vec::from_hex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap();
let info = Vec::from_hex("f0f1f2f3f4f5f6f7f8f9").unwrap();
let hkdf = Hkdf::<sha256::Hash>::new(&salt, &ikm);
let hkdf = Hkdf::<sha256::HashEngine>::new(&salt, &ikm);
let mut okm = [0u8; 1];
hkdf.expand(&info, &mut okm).unwrap();
@ -205,7 +205,7 @@ mod tests {
let ikm = Vec::from_hex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap();
let info = Vec::from_hex("f0f1f2f3f4f5f6f7f8f9").unwrap();
let hkdf = Hkdf::<sha256::Hash>::new(&salt, &ikm);
let hkdf = Hkdf::<sha256::HashEngine>::new(&salt, &ikm);
let okm = hkdf.expand_to_len(&info, 42).unwrap();
assert_eq!(
@ -219,7 +219,7 @@ mod tests {
let salt = Vec::from_hex("000102030405060708090a0b0c").unwrap();
let ikm = Vec::from_hex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap();
let hkdf = Hkdf::<sha256::Hash>::new(&salt, &ikm);
let hkdf = Hkdf::<sha256::HashEngine>::new(&salt, &ikm);
let debug = alloc::format!("{:?}", hkdf);
assert_eq!(debug, "Hkdf(#ec7bd36ab2ed4045)");

View File

@ -12,36 +12,26 @@ use core::{convert, fmt, str};
#[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::{GeneralHash, Hash, HashEngine};
use crate::{Hash, HashEngine};
/// A hash computed from a RFC 2104 HMAC. Parameterized by the underlying hash function.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct Hmac<T: GeneralHash>(T);
pub struct Hmac<T: Hash>(T);
impl<T: GeneralHash> Hmac<T> {
/// Constructs a new keyed HMAC engine from `key`.
pub fn engine(key: &[u8]) -> HmacEngine<T>
where
<T as GeneralHash>::Engine: Default,
{
HmacEngine::new(key)
}
}
impl<T: GeneralHash + str::FromStr> str::FromStr for Hmac<T> {
impl<T: Hash + str::FromStr> str::FromStr for Hmac<T> {
type Err = <T as str::FromStr>::Err;
fn from_str(s: &str) -> Result<Self, Self::Err> { Ok(Hmac(str::FromStr::from_str(s)?)) }
}
/// Pair of underlying hash engines, used for the inner and outer hash of HMAC.
#[derive(Debug, Clone)]
pub struct HmacEngine<T: GeneralHash> {
iengine: T::Engine,
oengine: T::Engine,
pub struct HmacEngine<T: HashEngine> {
iengine: T,
oengine: T,
}
impl<T: GeneralHash> HmacEngine<T> {
impl<T: HashEngine> HmacEngine<T> {
/// Constructs a new keyed HMAC engine from `key`.
///
/// We only support underlying hashes whose block sizes are ≤ 128 bytes.
@ -51,24 +41,23 @@ impl<T: GeneralHash> HmacEngine<T> {
/// Larger hashes will result in a panic.
pub fn new(key: &[u8]) -> HmacEngine<T>
where
<T as GeneralHash>::Engine: Default,
T: Default,
{
debug_assert!(T::Engine::BLOCK_SIZE <= 128);
debug_assert!(T::BLOCK_SIZE <= 128);
let mut ipad = [0x36u8; 128];
let mut opad = [0x5cu8; 128];
let mut ret = HmacEngine {
iengine: <T as GeneralHash>::engine(),
oengine: <T as GeneralHash>::engine(),
};
let mut ret = HmacEngine { iengine: T::default(), oengine: T::default() };
if key.len() > T::Engine::BLOCK_SIZE {
let hash = <T as GeneralHash>::hash(key);
let hash = hash.as_byte_array().as_ref();
for (b_i, b_h) in ipad.iter_mut().zip(hash) {
if key.len() > T::BLOCK_SIZE {
let mut engine = T::default();
engine.input(key);
let hash = engine.finalize();
for (b_i, b_h) in ipad.iter_mut().zip(hash.as_ref()) {
*b_i ^= *b_h;
}
for (b_o, b_h) in opad.iter_mut().zip(hash) {
for (b_o, b_h) in opad.iter_mut().zip(hash.as_ref()) {
*b_o ^= *b_h;
}
} else {
@ -80,55 +69,49 @@ impl<T: GeneralHash> HmacEngine<T> {
}
};
HashEngine::input(&mut ret.iengine, &ipad[..T::Engine::BLOCK_SIZE]);
HashEngine::input(&mut ret.oengine, &opad[..T::Engine::BLOCK_SIZE]);
ret.iengine.input(&ipad[..T::BLOCK_SIZE]);
ret.oengine.input(&opad[..T::BLOCK_SIZE]);
ret
}
/// A special constructor giving direct access to the underlying "inner" and "outer" engines.
pub fn from_inner_engines(iengine: T::Engine, oengine: T::Engine) -> HmacEngine<T> {
pub fn from_inner_engines(iengine: T, oengine: T) -> HmacEngine<T> {
HmacEngine { iengine, oengine }
}
}
impl<T: GeneralHash> HashEngine for HmacEngine<T> {
type Hash = Hmac<T>;
const BLOCK_SIZE: usize = T::Engine::BLOCK_SIZE;
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() }
fn input(&mut self, buf: &[u8]) { self.iengine.input(buf) }
fn finalize(self) -> Self::Hash { Hmac::from_engine(self) }
fn finalize(mut self) -> Self::Hash {
let ihash = self.iengine.finalize();
self.oengine.input(ihash.as_ref());
Hmac(self.oengine.finalize())
}
}
impl<T: GeneralHash + fmt::Debug> fmt::Debug for Hmac<T> {
impl<T: Hash + fmt::Debug> fmt::Debug for Hmac<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.0, f) }
}
impl<T: GeneralHash + fmt::Display> fmt::Display for Hmac<T> {
impl<T: Hash + fmt::Display> fmt::Display for Hmac<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
}
impl<T: GeneralHash + fmt::LowerHex> fmt::LowerHex for Hmac<T> {
impl<T: Hash + fmt::LowerHex> fmt::LowerHex for Hmac<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
}
impl<T: GeneralHash> convert::AsRef<[u8]> for Hmac<T> {
impl<T: Hash> convert::AsRef<[u8]> for Hmac<T> {
// Calling as_byte_array is more reliable
fn as_ref(&self) -> &[u8] { self.0.as_byte_array().as_ref() }
}
impl<T: GeneralHash> GeneralHash for Hmac<T> {
type Engine = HmacEngine<T>;
fn from_engine(mut e: HmacEngine<T>) -> Hmac<T> {
let ihash = T::from_engine(e.iengine);
e.oengine.input(ihash.as_byte_array().as_ref());
let ohash = T::from_engine(e.oengine);
Hmac(ohash)
}
}
impl<T: GeneralHash> Hash for Hmac<T> {
impl<T: Hash> Hash for Hmac<T> {
type Bytes = T::Bytes;
fn from_byte_array(bytes: T::Bytes) -> Self { Hmac(T::from_byte_array(bytes)) }
@ -144,14 +127,14 @@ impl<T: GeneralHash> Hash for Hmac<T> {
}
#[cfg(feature = "serde")]
impl<T: GeneralHash + Serialize> Serialize for Hmac<T> {
impl<T: Hash + Serialize> Serialize for Hmac<T> {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
Serialize::serialize(&self.0, s)
}
}
#[cfg(feature = "serde")]
impl<'de, T: GeneralHash + Deserialize<'de>> Deserialize<'de> for Hmac<T> {
impl<'de, T: Hash + Deserialize<'de>> Deserialize<'de> for Hmac<T> {
fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Hmac<T>, D::Error> {
let bytes = Deserialize::deserialize(d)?;
Ok(Hmac(bytes))
@ -166,14 +149,14 @@ crate::internal_macros::impl_write!(
Ok(buf.len())
},
|_us| { Ok(()) },
T: crate::GeneralHash
T: crate::HashEngine
);
#[cfg(test)]
mod tests {
#[test]
fn test() {
use crate::{sha256, GeneralHash as _, Hash as _, HashEngine, Hmac, HmacEngine};
use crate::{sha256, Hash as _, HashEngine, HmacEngine};
#[derive(Clone)]
struct Test {
@ -288,9 +271,9 @@ mod tests {
];
for test in tests {
let mut engine = HmacEngine::<sha256::Hash>::new(test.key);
let mut engine = HmacEngine::<sha256::HashEngine>::new(test.key);
engine.input(test.input);
let hash = Hmac::<sha256::Hash>::from_engine(engine);
let hash = engine.finalize();
assert_eq!(hash.as_ref(), test.output);
assert_eq!(hash.to_byte_array(), test.output);
}
@ -331,11 +314,11 @@ mod tests {
mod benches {
use test::Bencher;
use crate::{sha256, GeneralHash as _, HashEngine, Hmac};
use crate::{sha256, HashEngine as _, HmacEngine};
#[bench]
pub fn hmac_sha256_10(bh: &mut Bencher) {
let mut engine = Hmac::<sha256::Hash>::engine(&[]);
let mut engine = HmacEngine::<sha256::HashEngine>::new(&[]);
let bytes = [1u8; 10];
bh.iter(|| {
engine.input(&bytes);
@ -345,7 +328,7 @@ mod benches {
#[bench]
pub fn hmac_sha256_1k(bh: &mut Bencher) {
let mut engine = Hmac::<sha256::Hash>::engine(&[]);
let mut engine = HmacEngine::<sha256::HashEngine>::new(&[]);
let bytes = [1u8; 1024];
bh.iter(|| {
engine.input(&bytes);
@ -355,7 +338,7 @@ mod benches {
#[bench]
pub fn hmac_sha256_64k(bh: &mut Bencher) {
let mut engine = Hmac::<sha256::Hash>::engine(&[]);
let mut engine = HmacEngine::<sha256::HashEngine>::new(&[]);
let bytes = [1u8; 65536];
bh.iter(|| {
engine.input(&bytes);

View File

@ -189,6 +189,12 @@ pub trait HashEngine: Clone {
/// The `Hash` type returned when finalizing this engine.
type Hash: Hash;
/// The byte array that is used internally in `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;

View File

@ -88,6 +88,7 @@ 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 }

View File

@ -80,6 +80,7 @@ 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 }

View File

@ -129,6 +129,7 @@ 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 }

View File

@ -34,6 +34,7 @@ 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) }

View File

@ -134,6 +134,7 @@ 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) }

View File

@ -31,6 +31,7 @@ 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() }

View File

@ -121,6 +121,7 @@ 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 }

View File

@ -41,6 +41,7 @@ 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() }

View File

@ -122,6 +122,7 @@ impl HashEngine {
impl crate::HashEngine for HashEngine {
type Hash = Hash;
type Bytes = [u8; 8];
const BLOCK_SIZE: usize = 8;
#[inline]

View File

@ -8,7 +8,7 @@
use bitcoin_hashes::{
hash160, ripemd160, sha1, sha256, sha256d, sha256t, sha384, sha512, sha512_256, siphash24,
GeneralHash as _, HashEngine as _, Hmac, HmacEngine,
HashEngine as _, HmacEngine,
};
const DATA: &str = "arbitrary data to hash as a regression test";
@ -57,9 +57,9 @@ fn regression_sha256t() {
#[test]
fn regression_hmac_sha256_with_key() {
let mut engine = HmacEngine::<sha256::Hash>::new(HMAC_KEY);
let mut engine = HmacEngine::<sha256::HashEngine>::new(HMAC_KEY);
engine.input(DATA.as_bytes());
let hash = Hmac::from_engine(engine);
let hash = engine.finalize();
let got = format!("{}", hash);
let want = "d159cecaf4adf90b6a641bab767e4817d3a51c414acea3682686c35ec0b37b52";
@ -68,9 +68,9 @@ fn regression_hmac_sha256_with_key() {
#[test]
fn regression_hmac_sha512_with_key() {
let mut engine = HmacEngine::<sha512::Hash>::new(HMAC_KEY);
let mut engine = HmacEngine::<sha512::HashEngine>::new(HMAC_KEY);
engine.input(DATA.as_bytes());
let hash = Hmac::from_engine(engine);
let hash = engine.finalize();
let got = format!("{}", hash);
let want = "8511773748f89ba22c07fb3a2981a12c1823695119de41f4a62aead6b848bd34939acf16475c35ed7956114fead3e794cc162ecd35e447a4dabc3227d55f757b";

View File

@ -128,7 +128,7 @@ impl_write!(
Ok(buf.len())
},
|_us| { Ok(()) },
T: hashes::GeneralHash
T: hashes::HashEngine
);
/// Hashes data from a reader.
@ -172,7 +172,7 @@ mod sealed {
mod tests {
use alloc::format;
use hashes::{hmac, Hmac};
use hashes::hmac;
use super::*;
use crate::{Cursor, Write as _};
@ -257,24 +257,24 @@ mod tests {
#[test]
fn hmac() {
let mut engine = hmac::HmacEngine::<sha256::Hash>::new(&[0xde, 0xad, 0xbe, 0xef]);
let mut engine = hmac::HmacEngine::<sha256::HashEngine>::new(&[0xde, 0xad, 0xbe, 0xef]);
engine.write_all(&[]).unwrap();
assert_eq!(
format!("{}", hmac::Hmac::from_engine(engine)),
format!("{}", engine.finalize()),
"bf5515149cf797955c4d3194cca42472883281951697c8375d9d9b107f384225"
);
let mut engine = hmac::HmacEngine::<sha256::Hash>::new(&[0xde, 0xad, 0xbe, 0xef]);
let mut engine = hmac::HmacEngine::<sha256::HashEngine>::new(&[0xde, 0xad, 0xbe, 0xef]);
engine.write_all(&[1; 256]).unwrap();
assert_eq!(
format!("{}", hmac::Hmac::from_engine(engine)),
format!("{}", engine.finalize()),
"59c9aca10c81c73cb4c196d94db741b6bf2050e0153d5a45f2526bff34675ac5"
);
let mut engine = hmac::HmacEngine::<sha256::Hash>::new(&[0xde, 0xad, 0xbe, 0xef]);
let mut engine = hmac::HmacEngine::<sha256::HashEngine>::new(&[0xde, 0xad, 0xbe, 0xef]);
engine.write_all(&[99; 64000]).unwrap();
assert_eq!(
format!("{}", hmac::Hmac::from_engine(engine)),
format!("{}", engine.finalize()),
"30df499717415a395379a1eaabe50038036e4abb5afc94aa55c952f4aa57be08"
);
}
@ -345,9 +345,9 @@ mod tests {
#[test]
fn regression_hmac_sha256_with_key() {
let mut engine = HmacEngine::<sha256::Hash>::new(HMAC_KEY);
let mut engine = HmacEngine::<sha256::HashEngine>::new(HMAC_KEY);
engine.input(DATA.as_bytes());
let hash = Hmac::from_engine(engine);
let hash = engine.finalize();
let got = format!("{}", hash);
let want = "d159cecaf4adf90b6a641bab767e4817d3a51c414acea3682686c35ec0b37b52";
@ -356,9 +356,9 @@ mod tests {
#[test]
fn regression_hmac_sha512_with_key() {
let mut engine = HmacEngine::<sha512::Hash>::new(HMAC_KEY);
let mut engine = HmacEngine::<sha512::HashEngine>::new(HMAC_KEY);
engine.input(DATA.as_bytes());
let hash = Hmac::from_engine(engine);
let hash = engine.finalize();
let got = format!("{}", hash);
let want = "8511773748f89ba22c07fb3a2981a12c1823695119de41f4a62aead6b848bd34939acf16475c35ed7956114fead3e794cc162ecd35e447a4dabc3227d55f757b";