rust-api-template/src/api/backend/integrity_verification.rs

90 lines
2.0 KiB
Rust
Raw Normal View History

2025-05-31 15:57:05 +00:00
use blake3::{Hash, Hasher};
2025-05-04 20:17:09 +00:00
use crate::errors::ApiError;
pub trait CustomHash {
2025-05-31 15:57:05 +00:00
fn updater(&self, hasher: &mut Hasher);
2025-05-04 20:17:09 +00:00
2025-05-31 15:57:05 +00:00
fn hash(&self) -> Hash {
let mut hasher = Hasher::new();
2025-05-04 20:17:09 +00:00
Self::updater(&self, &mut hasher);
2025-05-31 15:57:05 +00:00
hasher.finalize()
2025-05-04 20:17:09 +00:00
}
}
pub struct IntegrityVerifier {
2025-05-31 15:57:05 +00:00
mac: Hasher,
2025-05-04 20:17:09 +00:00
}
impl IntegrityVerifier {
pub fn new() -> Result<Self, ApiError> {
Ok(Self {
2025-05-31 15:57:05 +00:00
mac: Hasher::new_derive_key(include_str!("./verification_secret")),
2025-05-04 20:17:09 +00:00
})
}
2025-05-31 15:57:05 +00:00
pub fn sign<T>(&self, data: &T) -> Result<Hash, ApiError>
2025-05-04 20:17:09 +00:00
where
T: CustomHash,
{
let mut mac = self.mac.clone();
2025-05-31 15:57:05 +00:00
mac.update(data.hash().as_bytes());
let signature = mac.finalize();
mac.reset();
2025-05-04 20:17:09 +00:00
2025-05-31 15:57:05 +00:00
Ok(signature)
2025-05-04 20:17:09 +00:00
}
2025-05-31 15:57:05 +00:00
pub fn verify<T>(&self, data: &T, signature: Hash) -> Result<(), ApiError>
2025-05-04 20:17:09 +00:00
where
T: CustomHash,
{
let mut mac = self.mac.clone();
2025-05-31 15:57:05 +00:00
mac.update(data.hash().as_bytes());
let verify = mac.finalize();
mac.reset();
2025-05-04 20:17:09 +00:00
2025-05-31 15:57:05 +00:00
match verify == signature {
true => Ok(()),
false => Err(ApiError::AccessDenied),
2025-05-04 20:17:09 +00:00
}
}
}
#[cfg(test)]
mod test {
2025-05-31 15:57:05 +00:00
use blake3::Hasher;
2025-05-04 20:17:09 +00:00
use crate::api::backend::integrity_verification::{CustomHash, IntegrityVerifier};
#[test]
fn integrity_verification() {
struct TestData {
one: u32,
two: String,
}
impl CustomHash for TestData {
2025-05-31 15:57:05 +00:00
fn updater(&self, hasher: &mut Hasher) {
2025-05-04 20:17:09 +00:00
hasher.update(&self.one.to_be_bytes());
hasher.update(&self.two.as_bytes());
}
}
let verifier = IntegrityVerifier::new().unwrap();
let mut item = TestData {
one: 24,
two: "MyTesting".to_string(),
};
let signature = verifier.sign(&item).unwrap();
2025-05-31 15:57:05 +00:00
assert!(verifier.verify(&item, signature).is_ok());
2025-05-04 20:17:09 +00:00
item.two = "Wrong".to_string();
2025-05-31 15:57:05 +00:00
assert!(verifier.verify(&item, signature).is_err());
2025-05-04 20:17:09 +00:00
}
}