pub const BYTES: usize = libsodium_sys::crypto_hash_sha512_BYTES as usize;
pub struct State {
state: libsodium_sys::crypto_hash_sha512_state,
}
impl Default for State {
fn default() -> Self {
Self::new()
}
}
impl State {
pub fn new() -> Self {
let mut state = Self {
state: unsafe { std::mem::zeroed() },
};
unsafe {
libsodium_sys::crypto_hash_sha512_init(&mut state.state);
}
state
}
pub fn update(&mut self, input: &[u8]) {
unsafe {
libsodium_sys::crypto_hash_sha512_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_sha512_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_sha512_statebytes() }
}
pub fn bytes() -> usize {
unsafe { libsodium_sys::crypto_hash_sha512_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,
"0e1e21ecf105ec853d24d728867ad70613c21663a4693074b2a3619c1bd39d66b588c33723bb466c72424e80e3ca63c249078ab347bab9428500e7ee43059d0d"
);
}
#[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,
"0e1e21ecf105ec853d24d728867ad70613c21663a4693074b2a3619c1bd39d66b588c33723bb466c72424e80e3ca63c249078ab347bab9428500e7ee43059d0d"
);
let one_shot_hash = crate::crypto_hash::hash_sha512(b"test data");
assert_eq!(result, one_shot_hash);
}
#[test]
fn test_statebytes() {
assert_eq!(
statebytes(),
std::mem::size_of::<libsodium_sys::crypto_hash_sha512_state>()
);
}
#[test]
fn test_bytes() {
assert_eq!(bytes(), BYTES);
}
}