use crate::classic::crypto_generichash::{
crypto_generichash, crypto_generichash_final, crypto_generichash_init,
crypto_generichash_update, GenericHashState,
};
use crate::constants::{CRYPTO_GENERICHASH_BYTES, CRYPTO_GENERICHASH_KEYBYTES};
use crate::error::Error;
pub use crate::types::*;
pub type Hash = StackByteArray<CRYPTO_GENERICHASH_BYTES>;
pub type Key = StackByteArray<CRYPTO_GENERICHASH_KEYBYTES>;
#[cfg(any(feature = "nightly", all(doc, not(doctest))))]
#[cfg_attr(all(feature = "nightly", doc), doc(cfg(feature = "nightly")))]
pub mod protected {
use super::*;
pub use crate::protected::*;
pub use crate::types::*;
pub type Key = HeapByteArray<CRYPTO_GENERICHASH_KEYBYTES>;
pub type Hash = HeapByteArray<CRYPTO_GENERICHASH_BYTES>;
}
pub struct GenericHash<const KEY_LENGTH: usize, const OUTPUT_LENGTH: usize> {
state: GenericHashState,
}
impl<const KEY_LENGTH: usize, const OUTPUT_LENGTH: usize> GenericHash<KEY_LENGTH, OUTPUT_LENGTH> {
pub fn new<Key: ByteArray<KEY_LENGTH>>(key: Option<&Key>) -> Result<Self, Error> {
Ok(Self {
state: crypto_generichash_init(key.map(|k| k.as_slice()), OUTPUT_LENGTH)?,
})
}
pub fn update<Input: Bytes + ?Sized>(&mut self, input: &Input) {
crypto_generichash_update(&mut self.state, input.as_slice())
}
pub fn finalize<Output: NewByteArray<OUTPUT_LENGTH>>(self) -> Result<Output, Error> {
let mut output = Output::new_byte_array();
crypto_generichash_final(self.state, output.as_mut_slice())?;
Ok(output)
}
pub fn finalize_to_vec(self) -> Result<Vec<u8>, Error> {
self.finalize()
}
pub fn hash<
Input: Bytes + ?Sized,
Key: ByteArray<KEY_LENGTH>,
Output: NewByteArray<OUTPUT_LENGTH>,
>(
input: &Input,
key: Option<&Key>,
) -> Result<Output, Error> {
let mut output = Output::new_byte_array();
crypto_generichash(
output.as_mut_slice(),
input.as_slice(),
key.map(|k| k.as_slice()),
)?;
Ok(output)
}
pub fn hash_to_vec<Input: Bytes, Key: ByteArray<KEY_LENGTH>>(
input: &Input,
key: Option<&Key>,
) -> Result<Vec<u8>, Error> {
Self::hash(input, key)
}
}
impl GenericHash<CRYPTO_GENERICHASH_KEYBYTES, CRYPTO_GENERICHASH_BYTES> {
pub fn new_with_defaults<Key: ByteArray<CRYPTO_GENERICHASH_KEYBYTES>>(
key: Option<&Key>,
) -> Result<Self, Error> {
Ok(Self {
state: crypto_generichash_init(key.map(|k| k.as_slice()), CRYPTO_GENERICHASH_BYTES)?,
})
}
pub fn hash_with_defaults<
Input: Bytes + ?Sized,
Key: ByteArray<CRYPTO_GENERICHASH_KEYBYTES>,
Output: NewByteArray<CRYPTO_GENERICHASH_BYTES>,
>(
input: &Input,
key: Option<&Key>,
) -> Result<Output, Error> {
Self::hash(input, key)
}
pub fn hash_with_defaults_to_vec<
Input: Bytes + ?Sized,
Key: ByteArray<CRYPTO_GENERICHASH_KEYBYTES>,
>(
input: &Input,
key: Option<&Key>,
) -> Result<Vec<u8>, Error> {
Self::hash(input, key)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_generichash() {
use base64::engine::general_purpose;
use base64::Engine as _;
let mut hasher = GenericHash::new_with_defaults::<Key>(None).expect("new hash failed");
hasher.update(b"hello");
let output: Vec<u8> = hasher.finalize().expect("finalize failed");
assert_eq!(
general_purpose::STANDARD.encode(output),
"Mk3PAn3UowqTLEQfNlol6GsXPe+kuOWJSCU0cbgbcs8="
);
let mut hasher = GenericHash::new_with_defaults::<Key>(None).expect("new hash failed");
hasher.update(b"hello");
let output = hasher.finalize_to_vec().expect("finalize failed");
assert_eq!(
general_purpose::STANDARD.encode(output),
"Mk3PAn3UowqTLEQfNlol6GsXPe+kuOWJSCU0cbgbcs8="
);
}
#[test]
fn test_generichash_onetime() {
use base64::engine::general_purpose;
use base64::Engine as _;
let output: Hash =
GenericHash::hash(b"hello", Some(b"a very secret key")).expect("hash failed");
assert_eq!(
general_purpose::STANDARD.encode(&output),
"AECDe+XJsB6nOkbCsbS/OPXdzpcRm3AolW/Bg1LFY9A="
);
let output: Vec<u8> =
GenericHash::hash_with_defaults::<_, Key, _>(b"hello", None).expect("hash failed");
assert_eq!(
general_purpose::STANDARD.encode(output),
"Mk3PAn3UowqTLEQfNlol6GsXPe+kuOWJSCU0cbgbcs8="
);
let output =
GenericHash::hash_with_defaults_to_vec::<_, Key>(b"hello", None).expect("hash failed");
assert_eq!(
general_purpose::STANDARD.encode(output),
"Mk3PAn3UowqTLEQfNlol6GsXPe+kuOWJSCU0cbgbcs8="
);
}
#[test]
fn test_generichash_onetime_empty() {
use base64::engine::general_purpose;
use base64::Engine as _;
let output =
GenericHash::hash_with_defaults_to_vec::<_, Key>(&[], None).expect("hash failed");
assert_eq!(
general_purpose::STANDARD.encode(output),
"DldRwCblQ7Loqy6wYJnaodHl30d3j3eH+qtFzfEv46g="
);
}
#[test]
fn test_vectors() {
let test_vec = |input, key, hash| {
let input = hex::decode(input).expect("decode input");
let key = hex::decode(key).expect("decode key");
let expected_hash = hex::decode(hash).expect("decode hash");
let hash: Vec<u8> =
GenericHash::<64, 64>::hash(&input, Some(&key)).expect("hash failed");
assert_eq!(expected_hash, hash);
};
test_vec("", "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "10ebb67700b1868efb4417987acf4690ae9d972fb7a590c2f02871799aaa4786b5e996e8f0f4eb981fc214b005f42d2ff4233499391653df7aefcbc13fc51568");
test_vec("00", "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "961f6dd1e4dd30f63901690c512e78e4b45e4742ed197c3c5e45c549fd25f2e4187b0bc9fe30492b16b0d0bc4ef9b0f34c7003fac09a5ef1532e69430234cebd");
test_vec("0001", "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "da2cfbe2d8409a0f38026113884f84b50156371ae304c4430173d08a99d9fb1b983164a3770706d537f49e0c916d9f32b95cc37a95b99d857436f0232c88a965");
test_vec("000102", "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "33d0825dddf7ada99b0e7e307104ad07ca9cfd9692214f1561356315e784f3e5a17e364ae9dbb14cb2036df932b77f4b292761365fb328de7afdc6d8998f5fc1");
test_vec("00010203", "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "beaa5a3d08f3807143cf621d95cd690514d0b49efff9c91d24b59241ec0eefa5f60196d407048bba8d2146828ebcb0488d8842fd56bb4f6df8e19c4b4daab8ac");
test_vec("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfc", "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "a6213743568e3b3158b9184301f3690847554c68457cb40fc9a4b8cfd8d4a118c301a07737aeda0f929c68913c5f51c80394f53bff1c3e83b2e40ca97eba9e15");
test_vec("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfd", "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "d444bfa2362a96df213d070e33fa841f51334e4e76866b8139e8af3bb3398be2dfaddcbc56b9146de9f68118dc5829e74b0c28d7711907b121f9161cb92b69a9");
test_vec("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe", "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "142709d62e28fcccd0af97fad0f8465b971e82201dc51070faa0372aa43e92484be1c1e73ba10906d5d1853db6a4106e0a7bf9800d373d6dee2d46d62ef2a461");
}
}