use crate::types::{EncFileError, HashAlg};
use std::fs::File;
use std::io::{BufReader, Read};
use std::path::Path;
pub fn hash_bytes(data: &[u8], alg: HashAlg) -> Vec<u8> {
match alg {
HashAlg::Blake3 => {
let mut hasher = blake3::Hasher::new();
hasher.update(data);
hasher.finalize().as_bytes().to_vec() }
HashAlg::Sha256 => {
use sha2::{Digest, Sha256};
Sha256::digest(data).to_vec() }
HashAlg::Sha512 => {
use sha2::{Digest, Sha512};
Sha512::digest(data).to_vec() }
HashAlg::Sha3_256 => {
use sha3::{Digest, Sha3_256};
Sha3_256::digest(data).to_vec() }
HashAlg::Sha3_512 => {
use sha3::{Digest, Sha3_512};
Sha3_512::digest(data).to_vec() }
HashAlg::Blake2b => {
use blake2::{Blake2b512, Digest};
Blake2b512::digest(data).to_vec() }
HashAlg::Xxh3_64 => {
use xxhash_rust::xxh3::xxh3_64;
xxh3_64(data).to_be_bytes().to_vec() }
HashAlg::Xxh3_128 => {
use xxhash_rust::xxh3::xxh3_128;
xxh3_128(data).to_be_bytes().to_vec() }
HashAlg::Crc32 => {
use crc::{CRC_32_ISO_HDLC, Crc};
let crc = Crc::<u32>::new(&CRC_32_ISO_HDLC);
let mut d = crc.digest();
d.update(data);
d.finalize().to_be_bytes().to_vec() }
}
}
pub fn hash_file(path: &Path, alg: HashAlg) -> Result<Vec<u8>, EncFileError> {
let mut file = File::open(path)?;
let mut reader = BufReader::new(&mut file);
let mut buf = vec![0u8; 64 * 1024];
match alg {
HashAlg::Blake3 => {
let mut h = blake3::Hasher::new();
loop {
let n = reader.read(&mut buf)?;
if n == 0 {
break;
}
h.update(&buf[..n]);
}
Ok(h.finalize().as_bytes().to_vec())
}
HashAlg::Sha256 => {
use sha2::{Digest, Sha256};
let mut h = Sha256::default();
loop {
let n = reader.read(&mut buf)?;
if n == 0 {
break;
}
h.update(&buf[..n]);
}
Ok(h.finalize().to_vec())
}
HashAlg::Sha512 => {
use sha2::{Digest, Sha512};
let mut h = Sha512::default();
loop {
let n = reader.read(&mut buf)?;
if n == 0 {
break;
}
h.update(&buf[..n]);
}
Ok(h.finalize().to_vec())
}
HashAlg::Sha3_256 => {
use sha3::{Digest, Sha3_256};
let mut h = Sha3_256::default();
loop {
let n = reader.read(&mut buf)?;
if n == 0 {
break;
}
h.update(&buf[..n]);
}
Ok(h.finalize().to_vec())
}
HashAlg::Sha3_512 => {
use sha3::{Digest, Sha3_512};
let mut h = Sha3_512::default();
loop {
let n = reader.read(&mut buf)?;
if n == 0 {
break;
}
h.update(&buf[..n]);
}
Ok(h.finalize().to_vec())
}
HashAlg::Blake2b => {
use blake2::{Blake2b512, Digest};
let mut h = Blake2b512::default(); loop {
let n = reader.read(&mut buf)?;
if n == 0 {
break;
}
h.update(&buf[..n]);
}
Ok(h.finalize().to_vec())
}
HashAlg::Xxh3_64 => {
use xxhash_rust::xxh3::Xxh3;
let mut h = Xxh3::new();
loop {
let n = reader.read(&mut buf)?;
if n == 0 {
break;
}
h.update(&buf[..n]);
}
Ok(h.digest().to_be_bytes().to_vec())
}
HashAlg::Xxh3_128 => {
use xxhash_rust::xxh3::Xxh3;
let mut h = Xxh3::new();
loop {
let n = reader.read(&mut buf)?;
if n == 0 {
break;
}
h.update(&buf[..n]);
}
Ok(h.digest128().to_be_bytes().to_vec())
}
HashAlg::Crc32 => {
use crc::{CRC_32_ISO_HDLC, Crc};
let crc = Crc::<u32>::new(&CRC_32_ISO_HDLC);
let mut d = crc.digest();
loop {
let n = reader.read(&mut buf)?;
if n == 0 {
break;
}
d.update(&buf[..n]);
}
Ok(d.finalize().to_be_bytes().to_vec())
}
}
}
pub fn hash_bytes_keyed_blake3(data: &[u8], key32: &[u8; 32]) -> [u8; 32] {
blake3::keyed_hash(key32, data).into()
}
pub fn hash_file_keyed_blake3(path: &Path, key32: &[u8; 32]) -> Result<[u8; 32], EncFileError> {
let mut file = File::open(path)?;
let mut reader = BufReader::new(&mut file);
let mut buf = vec![0u8; 64 * 1024];
let mut hasher = blake3::Hasher::new_keyed(key32);
loop {
let n = reader.read(&mut buf)?;
if n == 0 {
break;
}
hasher.update(&buf[..n]);
}
Ok(*hasher.finalize().as_bytes())
}
pub fn to_hex_lower(bytes: &[u8]) -> String {
const HEX: &[u8; 16] = b"0123456789abcdef";
let mut out = String::with_capacity(bytes.len() * 2);
for &b in bytes {
out.push(HEX[(b >> 4) as usize] as char);
out.push(HEX[(b & 0x0f) as usize] as char);
}
out
}