use blake2b_simd::{Params, State};
use dusk_bls12_381::BlsScalar;
use dusk_bytes::Serializable;
pub struct Hasher {
state: State,
}
impl Default for Hasher {
fn default() -> Self {
Hasher {
state: Params::new().hash_length(BlsScalar::SIZE).to_state(),
}
}
}
impl Hasher {
pub fn new() -> Self {
Self::default()
}
pub fn update(&mut self, data: impl AsRef<[u8]>) {
self.state.update(data.as_ref());
}
pub fn chain_update(self, data: impl AsRef<[u8]>) -> Self {
let mut hasher = self;
hasher.state.update(data.as_ref());
hasher
}
pub fn output(self) -> [u8; BlsScalar::SIZE] {
let hasher = self;
let mut buf = [0u8; BlsScalar::SIZE];
buf.copy_from_slice(hasher.state.finalize().as_ref());
buf[BlsScalar::SIZE - 1] &= 0xf;
buf
}
pub fn finalize(self) -> BlsScalar {
BlsScalar::from_bytes(&self.output()).expect(
"Conversion to BlsScalar should never fail after truncation",
)
}
pub fn digest(data: impl AsRef<[u8]>) -> BlsScalar {
let mut hasher = Hasher::new();
hasher.update(data.as_ref());
hasher.finalize()
}
}