use crate::digest::{
generic_array::typenum::{PartialDiv, Unsigned},
BlockInput, Digest,
};
pub trait Tagged: Default + Clone {
fn tagged(&self, tag: &[u8]) -> Self;
}
impl<H: BlockInput + Digest + Default + Clone> Tagged for H
where
<H as BlockInput>::BlockSize: PartialDiv<H::OutputSize>,
<<H as BlockInput>::BlockSize as PartialDiv<H::OutputSize>>::Output: Unsigned,
{
fn tagged(&self, tag: &[u8]) -> Self {
let hashed_tag = {
let mut hash = H::default();
hash.update(tag);
hash.finalize()
};
let mut tagged_hash = self.clone();
let fill_block =
<<H::BlockSize as PartialDiv<H::OutputSize>>::Output as Unsigned>::to_usize();
for _ in 0..fill_block {
tagged_hash.update(&hashed_tag[..]);
}
tagged_hash
}
}
pub trait HashInto {
fn hash_into(&self, hash: &mut impl digest::Digest);
}
impl HashInto for [u8] {
fn hash_into(&self, hash: &mut impl digest::Digest) {
hash.update(self)
}
}
impl HashInto for str {
fn hash_into(&self, hash: &mut impl digest::Digest) {
hash.update(self.as_bytes())
}
}
pub trait HashAdd {
fn add<HI: HashInto + ?Sized>(self, data: &HI) -> Self;
}
impl<D: Digest> HashAdd for D {
fn add<HI: HashInto + ?Sized>(mut self, data: &HI) -> Self {
data.hash_into(&mut self);
self
}
}
pub trait AddTag {
fn add_protocol_tag(self, tag: &str) -> Self;
fn add_application_tag(self, tag: &str) -> Self;
}
impl AddTag for () {
fn add_protocol_tag(self, _tag: &str) -> Self {
()
}
fn add_application_tag(self, _tag: &str) -> Self {
()
}
}