pub(crate) mod cvstack;
pub(crate) mod internal;
pub(crate) mod state;
use crate::errors::UnknownCryptoError;
use crate::hazardous::hash::blake3::internal::KEYED_HASH;
use crate::hazardous::hash::blake3::state::Blake3State;
use crate::hazardous::mac::blake3::SecretKey;
#[cfg(feature = "safe_api")]
use std::io;
#[derive(PartialEq, Debug, Clone)]
pub struct Blake3 {
internal: Blake3State,
flags: u32,
}
impl Default for Blake3 {
fn default() -> Self {
Self {
internal: Blake3State::new_with_iv(0),
flags: 0,
}
}
}
impl Blake3 {
pub fn new() -> Self {
Self::default()
}
pub fn new_keyed(secret_key: &SecretKey) -> Self {
Self {
internal: Blake3State::new(secret_key, KEYED_HASH),
flags: KEYED_HASH,
}
}
pub fn reset(&mut self) {
self.internal.reset();
}
#[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."]
pub fn absorb(&mut self, data: &[u8]) -> Result<(), UnknownCryptoError> {
self.internal.absorb(data, self.flags)
}
#[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."]
pub fn squeeze(&mut self, dest: &mut [u8]) -> Result<(), UnknownCryptoError> {
self.internal.squeeze(dest, self.flags)
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "safe_api")))]
#[cfg(feature = "safe_api")]
impl io::Write for Blake3 {
fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
self.absorb(bytes).map_err(io::Error::other)?;
Ok(bytes.len())
}
fn flush(&mut self) -> Result<(), io::Error> {
Ok(())
}
}
#[cfg(test)]
mod test_xof_interface {
use crate::hazardous::hash::blake3::internal::BLOCK_LEN;
use crate::hazardous::hash::blake3::*;
use crate::test_framework::xof_interface::{TestableXofContext, XofContextConsistencyTester};
impl TestableXofContext for Blake3 {
fn reset(&mut self) -> Result<(), UnknownCryptoError> {
self.reset();
Ok(())
}
fn absorb(&mut self, input: &[u8]) -> Result<(), UnknownCryptoError> {
self.absorb(input)
}
fn squeeze(&mut self, dst: &mut [u8]) -> Result<(), UnknownCryptoError> {
self.squeeze(dst)
}
fn compare_states(state_1: &Self, state_2: &Self) {
assert_eq!(state_1, state_2)
}
}
#[test]
fn default_consistency_states() {
let test_runner = XofContextConsistencyTester::<Blake3>::new(Blake3::new(), BLOCK_LEN);
test_runner.run_all_tests();
}
#[quickcheck]
#[cfg(feature = "safe_api")]
fn prop_input_to_consistency(data: Vec<u8>) -> bool {
let test_runner = XofContextConsistencyTester::<Blake3>::new(Blake3::new(), BLOCK_LEN);
test_runner.run_all_tests_property(&data);
true
}
#[cfg(feature = "safe_api")]
mod test_io_impls {
use std::io::Write;
use crate::hazardous::hash::blake3::Blake3;
#[quickcheck]
fn prop_hasher_write_same_as_update(data: Vec<u8>, outlen: u16) -> bool {
let mut hasher_a = Blake3::new();
let mut hasher_b = hasher_a.clone();
hasher_a.absorb(&data).unwrap();
hasher_b.write_all(&data).unwrap();
hasher_b.flush().unwrap();
assert_eq!(hasher_a, hasher_b);
let mut hash_a = vec![0u8; outlen as usize];
let mut hash_b = vec![0u8; outlen as usize];
hasher_a.squeeze(&mut hash_a).unwrap();
hasher_b.squeeze(&mut hash_b).unwrap();
hasher_b.flush().unwrap();
assert_eq!(hasher_a, hasher_b);
hash_a == hash_b
}
}
}