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:
parent
ab63b7a0ff
commit
e1bac7da55
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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)");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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() }
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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() }
|
||||
|
|
|
@ -122,6 +122,7 @@ impl HashEngine {
|
|||
|
||||
impl crate::HashEngine for HashEngine {
|
||||
type Hash = Hash;
|
||||
type Bytes = [u8; 8];
|
||||
const BLOCK_SIZE: usize = 8;
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
Loading…
Reference in New Issue