From 62521be3635ac7d9c8e5f1e570df8e3c8aa789fb Mon Sep 17 00:00:00 2001 From: Hlars Date: Sun, 4 May 2025 22:17:09 +0200 Subject: [PATCH] changes --- src/api/backend/integrity_verification.rs | 90 +++++++++++++++++++++++ src/api/backend/mod.rs | 7 +- 2 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 src/api/backend/integrity_verification.rs diff --git a/src/api/backend/integrity_verification.rs b/src/api/backend/integrity_verification.rs new file mode 100644 index 0000000..d15c844 --- /dev/null +++ b/src/api/backend/integrity_verification.rs @@ -0,0 +1,90 @@ +use hmac::{Hmac, Mac}; +use sha2::{Digest, Sha512}; + +use crate::errors::ApiError; + +type HashType = Sha512; + +pub trait CustomHash { + fn updater(&self, hasher: &mut Sha512); + + fn hash(&self) -> Vec { + let mut hasher = Sha512::new(); + Self::updater(&self, &mut hasher); + hasher.finalize().to_vec() + } +} + +pub struct IntegrityVerifier { + mac: Hmac, +} + +impl IntegrityVerifier { + pub fn new() -> Result { + Ok(Self { + mac: Hmac::::new_from_slice( + include_str!("./verification_secret").as_bytes(), + )?, + }) + } + + pub fn sign(&self, data: &T) -> Result, ApiError> + where + T: CustomHash, + { + let mut mac = self.mac.clone(); + + mac.update(&data.hash()); + let signature = mac.finalize_reset().into_bytes(); + + Ok(signature.to_vec()) + } + + pub fn verify(&self, data: &T, signature: &[u8]) -> Result<(), ApiError> + where + T: CustomHash, + { + let mut mac = self.mac.clone(); + mac.update(&data.hash()); + + match mac.verify_slice_reset(signature) { + Ok(_) => Ok(()), + Err(_e) => Err(ApiError::AccessDenied), + } + } +} + +#[cfg(test)] +mod test { + use hmac::digest::Update; + + use crate::api::backend::integrity_verification::{CustomHash, IntegrityVerifier}; + + #[test] + fn integrity_verification() { + struct TestData { + one: u32, + two: String, + } + + impl CustomHash for TestData { + fn updater(&self, hasher: &mut sha2::Sha512) { + 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(); + assert!(verifier.verify(&item, &signature).is_ok()); + + item.two = "Wrong".to_string(); + assert!(verifier.verify(&item, &signature).is_err()); + } +} diff --git a/src/api/backend/mod.rs b/src/api/backend/mod.rs index cf6736c..83c0341 100644 --- a/src/api/backend/mod.rs +++ b/src/api/backend/mod.rs @@ -7,6 +7,7 @@ use crate::{api::routes::users::sql::get_users, config::Configuration, errors::A use super::routes::{auth::models::Credentials, models::Status, users::models::User}; +pub mod integrity_verification; pub mod ldap; pub mod private_key_cache; @@ -65,8 +66,10 @@ impl AuthBackend for ApiBackend { // terminate connection ldap.unbind().await; } else { - argon2::verify_encoded(&user.password, password.as_bytes()) - .map_err(|_| ApiError::InvalidCredentials)?; + match argon2::verify_encoded(&user.password, password.as_bytes()) { + Ok(true) => {} + _ => return Err(ApiError::InvalidCredentials), + }; } Ok(Some(user.clone()))