pub const BYTES: usize = libsodium_sys::crypto_hash_sha3512_BYTES as usize;
pub struct State {
state: libsodium_sys::crypto_hash_sha3512_state,
}
impl Default for State {
fn default() -> Self {
Self::new()
}
}
impl State {
pub fn new() -> Self {
let mut state = std::mem::MaybeUninit::uninit();
let state_ptr = state.as_mut_ptr();
unsafe {
libsodium_sys::crypto_hash_sha3512_init(state_ptr);
Self {
state: state.assume_init(),
}
}
}
pub fn update(&mut self, input: &[u8]) {
unsafe {
libsodium_sys::crypto_hash_sha3512_update(
&mut self.state,
input.as_ptr(),
input.len() as u64,
);
}
}
pub fn finalize(&mut self) -> [u8; BYTES] {
let mut hash = [0u8; BYTES];
unsafe {
libsodium_sys::crypto_hash_sha3512_final(&mut self.state, hash.as_mut_ptr());
}
hash
}
}
pub fn hash(data: &[u8]) -> [u8; BYTES] {
let mut state = State::new();
state.update(data);
state.finalize()
}
pub fn statebytes() -> usize {
unsafe { libsodium_sys::crypto_hash_sha3512_statebytes() }
}
pub fn bytes() -> usize {
unsafe { libsodium_sys::crypto_hash_sha3512_bytes() }
}
#[cfg(test)]
mod tests {
use super::*;
use ct_codecs::{Encoder, Hex};
#[test]
fn test_hash() {
let data = b"test data";
let hash = hash(data);
let mut encoded = vec![0u8; hash.len() * 2];
let encoded = Hex::encode(&mut encoded, hash).unwrap();
let hash_hex = std::str::from_utf8(encoded).unwrap();
assert_eq!(
hash_hex,
"bb9e2a02237e6f8adcaef9fc14b898b7c80cedc114110472cdf925233621b705963c76e7b113bed3c278ff11671a6d1cdcba545e009ff4c0c02539899241993b"
);
}
#[test]
fn test_incremental_hash() {
let mut state = State::new();
state.update(b"test ");
state.update(b"data");
let result = state.finalize();
let mut encoded = vec![0u8; result.len() * 2];
let encoded = Hex::encode(&mut encoded, result).unwrap();
let hash_hex = std::str::from_utf8(encoded).unwrap();
assert_eq!(
hash_hex,
"bb9e2a02237e6f8adcaef9fc14b898b7c80cedc114110472cdf925233621b705963c76e7b113bed3c278ff11671a6d1cdcba545e009ff4c0c02539899241993b"
);
assert_eq!(result, crate::crypto_hash::hash_sha3512(b"test data"));
}
#[test]
fn test_statebytes() {
assert_eq!(
statebytes(),
std::mem::size_of::<libsodium_sys::crypto_hash_sha3512_state>()
);
}
#[test]
fn test_bytes() {
assert_eq!(bytes(), BYTES);
}
}