use crate::ops::hash;
use crate::ops::hash::reference::kdf::Argon2idParams;
pub fn md5(input: &[u8], output: &mut Vec<u8>) {
extend_u32s(output, &hash::md5::md5(input));
}
pub fn sha1(input: &[u8], output: &mut Vec<u8>) {
extend_u32s(output, &hash::sha1::sha1(input));
}
pub fn sha256(input: &[u8], output: &mut Vec<u8>) {
extend_u32s(output, &hash::sha256::sha256(input));
}
pub fn sha384(input: &[u8], output: &mut Vec<u8>) {
extend_u64s(output, &hash::sha384::sha384(input));
}
pub fn sha512(input: &[u8], output: &mut Vec<u8>) {
extend_u64s(output, &hash::sha512::sha512(input));
}
pub fn sha3_256(input: &[u8], output: &mut Vec<u8>) {
extend_u32s(output, &hash::sha3_256::sha3_256(input));
}
pub fn sha3_512(input: &[u8], output: &mut Vec<u8>) {
extend_u64s(output, &hash::sha3_512::sha3_512(input));
}
pub fn blake2b(input: &[u8], output: &mut Vec<u8>) {
extend_u64s(output, &hash::blake2b::blake2b(input));
}
pub fn blake2s(input: &[u8], output: &mut Vec<u8>) {
extend_u32s(output, &hash::blake2s::blake2s(input));
}
pub fn blake3(input: &[u8], output: &mut Vec<u8>) {
extend_u32s(output, &hash::blake3::blake3(input));
}
pub fn ripemd160(input: &[u8], output: &mut Vec<u8>) {
extend_u32s(output, &hash::ripemd160::ripemd160(input));
}
pub fn xxhash64(input: &[u8], output: &mut Vec<u8>) {
output.clear();
output.extend_from_slice(&hash::xxhash64::xxhash64(input).to_le_bytes());
}
pub fn xxhash3_64(input: &[u8], output: &mut Vec<u8>) {
output.clear();
output.extend_from_slice(&hash::xxhash3_64::xxhash3_64(input).to_le_bytes());
}
pub fn hmac_md5(input: &[u8], output: &mut Vec<u8>) {
let (key, msg) = split_half(input);
extend_u32s(output, &hash::hmac_md5::hmac_md5(key, msg));
}
pub fn hmac_sha1(input: &[u8], output: &mut Vec<u8>) {
let (key, msg) = split_half(input);
extend_u32s(output, &hash::hmac_sha1::hmac_sha1(key, msg));
}
pub fn hmac_sha256(input: &[u8], output: &mut Vec<u8>) {
let (key, msg) = split_half(input);
extend_u32s(output, &hash::hmac_sha256::hmac_sha256(key, msg));
}
pub fn hkdf_extract(input: &[u8], output: &mut Vec<u8>) {
let (salt, ikm) = split_half(input);
extend_u32s(output, &hash::hkdf_extract::hkdf_extract(salt, ikm));
}
pub fn hkdf_expand(input: &[u8], output: &mut Vec<u8>) {
let (payload, length) = split_trailing_u32(input);
let (prk, info) = split_half(payload);
write_result(output, hash::hkdf_expand::hkdf_expand(prk, info, length));
}
pub fn pbkdf2_sha256(input: &[u8], output: &mut Vec<u8>) {
let (payload, dk_len) = split_trailing_u32(input);
let (payload, iterations) = split_trailing_u32(payload);
let (password, salt) = split_half(payload);
write_result(
output,
hash::pbkdf2_sha256::pbkdf2_sha256(password, salt, iterations, dk_len),
);
}
pub fn argon2id(input: &[u8], output: &mut Vec<u8>) {
let (password, salt) = split_half(input);
let params = Argon2idParams {
memory_kib: 32,
iterations: 1,
parallelism: 1,
output_len: 32,
};
write_result(output, hash::argon2id::argon2id(password, salt, params));
}
pub fn siphash13(input: &[u8], output: &mut Vec<u8>) {
let (msg, key) = split_trailing_u64(input);
output.clear();
output.extend_from_slice(&hash::siphash13::siphash13(msg, key).to_le_bytes());
}
fn extend_u32s(output: &mut Vec<u8>, words: &[u32]) {
output.clear();
for word in words {
output.extend_from_slice(&word.to_le_bytes());
}
}
fn extend_u64s(output: &mut Vec<u8>, words: &[u64]) {
output.clear();
for word in words {
output.extend_from_slice(&word.to_le_bytes());
}
}
fn split_half(input: &[u8]) -> (&[u8], &[u8]) {
input.split_at(input.len() / 2)
}
fn split_trailing_u32(input: &[u8]) -> (&[u8], u32) {
if input.len() < 4 {
return (input, 0);
}
let split = input.len() - 4;
let value = u32::from_le_bytes([
input[split],
input[split + 1],
input[split + 2],
input[split + 3],
]);
(&input[..split], value)
}
fn split_trailing_u64(input: &[u8]) -> (&[u8], u64) {
if input.len() < 8 {
return (input, 0);
}
let split = input.len() - 8;
let value = u64::from_le_bytes([
input[split],
input[split + 1],
input[split + 2],
input[split + 3],
input[split + 4],
input[split + 5],
input[split + 6],
input[split + 7],
]);
(&input[..split], value)
}
fn write_result(output: &mut Vec<u8>, result: Result<Vec<u8>, String>) {
output.clear();
match result {
Ok(bytes) => output.extend_from_slice(&bytes),
Err(error) => tracing::error!("{error}. Fix: provide valid hash intrinsic parameters."),
}
}