use crate::errors::UnknownCryptoError;
#[cfg(feature = "safe_api")]
use std::io;
use super::Sha3;
pub const SHA3_224_RATE: usize = 144;
pub const SHA3_224_OUTSIZE: usize = 28;
construct_public! {
(Digest, test_digest, SHA3_224_OUTSIZE, SHA3_224_OUTSIZE)
}
impl_from_trait!(Digest, SHA3_224_OUTSIZE);
#[derive(Clone, Debug)]
pub struct Sha3_224 {
pub(crate) _state: Sha3<SHA3_224_RATE>,
}
impl Default for Sha3_224 {
fn default() -> Self {
Self::new()
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "safe_api")))]
#[cfg(feature = "safe_api")]
impl io::Write for Sha3_224 {
fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
self.update(bytes).map_err(io::Error::other)?;
Ok(bytes.len())
}
fn flush(&mut self) -> Result<(), io::Error> {
Ok(())
}
}
impl Sha3_224 {
pub fn new() -> Self {
Self {
_state: Sha3::<SHA3_224_RATE>::_new(56),
}
}
pub fn reset(&mut self) {
self._state._reset();
}
#[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."]
pub fn update(&mut self, data: &[u8]) -> Result<(), UnknownCryptoError> {
self._state._update(data)
}
pub(crate) fn _finalize_internal(&mut self, dest: &mut [u8]) -> Result<(), UnknownCryptoError> {
self._state._finalize(dest)
}
#[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."]
pub fn finalize(&mut self) -> Result<Digest, UnknownCryptoError> {
let mut digest = [0u8; SHA3_224_OUTSIZE];
self._finalize_internal(&mut digest)?;
Ok(Digest::from(digest))
}
#[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."]
pub fn digest(data: &[u8]) -> Result<Digest, UnknownCryptoError> {
let mut ctx = Self::new();
ctx.update(data)?;
ctx.finalize()
}
}
#[cfg(test)]
mod public {
use super::*;
#[test]
fn test_default_equals_new() {
let new = Sha3_224::new();
let default = Sha3_224::default();
new._state.compare_state_to_other(&default._state);
}
#[test]
#[cfg(feature = "safe_api")]
fn test_debug_impl() {
let initial_state = Sha3_224::new();
let debug = format!("{initial_state:?}");
let expected = "Sha3_224 { _state: State { state: [***OMITTED***], buffer: [***OMITTED***], capacity: 56, leftover: 0, is_finalized: false } }";
assert_eq!(debug, expected);
}
mod test_streaming_interface {
use super::*;
use crate::test_framework::incremental_interface::*;
impl TestableStreamingContext<Digest> for Sha3_224 {
fn reset(&mut self) -> Result<(), UnknownCryptoError> {
self.reset();
Ok(())
}
fn update(&mut self, input: &[u8]) -> Result<(), UnknownCryptoError> {
self.update(input)
}
fn finalize(&mut self) -> Result<Digest, UnknownCryptoError> {
self.finalize()
}
fn one_shot(input: &[u8]) -> Result<Digest, UnknownCryptoError> {
Sha3_224::digest(input)
}
fn verify_result(expected: &Digest, input: &[u8]) -> Result<(), UnknownCryptoError> {
let actual: Digest = Self::one_shot(input)?;
if &actual == expected {
Ok(())
} else {
Err(UnknownCryptoError)
}
}
fn compare_states(state_1: &Sha3_224, state_2: &Sha3_224) {
state_1._state.compare_state_to_other(&state_2._state);
}
}
#[test]
fn default_consistency_tests() {
let initial_state: Sha3_224 = Sha3_224::new();
let test_runner = StreamingContextConsistencyTester::<Digest, Sha3_224>::new(
initial_state,
SHA3_224_RATE,
);
test_runner.run_all_tests();
}
#[quickcheck]
#[cfg(feature = "safe_api")]
fn prop_input_to_consistency(data: Vec<u8>) -> bool {
let initial_state: Sha3_224 = Sha3_224::new();
let test_runner = StreamingContextConsistencyTester::<Digest, Sha3_224>::new(
initial_state,
SHA3_224_RATE,
);
test_runner.run_all_tests_property(&data);
true
}
}
#[cfg(feature = "safe_api")]
mod test_io_impls {
use crate::hazardous::hash::sha3::sha3_224::Sha3_224;
use std::io::Write;
#[quickcheck]
fn prop_hasher_write_same_as_update(data: Vec<u8>) -> bool {
let mut hasher_a = Sha3_224::new();
let mut hasher_b = hasher_a.clone();
hasher_a.update(&data).unwrap();
hasher_b.write_all(&data).unwrap();
hasher_b.flush().unwrap();
hasher_a._state.compare_state_to_other(&hasher_b._state);
let hash_a = hasher_a.finalize().unwrap();
let hash_b = hasher_b.finalize().unwrap();
hasher_b.flush().unwrap();
hasher_a._state.compare_state_to_other(&hasher_b._state);
hash_a == hash_b
}
}
}