This commit is contained in:
Hlars 2025-05-04 22:17:09 +02:00
parent 33dd7c5ffc
commit 62521be363
2 changed files with 95 additions and 2 deletions

View File

@ -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<u8> {
let mut hasher = Sha512::new();
Self::updater(&self, &mut hasher);
hasher.finalize().to_vec()
}
}
pub struct IntegrityVerifier {
mac: Hmac<HashType>,
}
impl IntegrityVerifier {
pub fn new() -> Result<Self, ApiError> {
Ok(Self {
mac: Hmac::<HashType>::new_from_slice(
include_str!("./verification_secret").as_bytes(),
)?,
})
}
pub fn sign<T>(&self, data: &T) -> Result<Vec<u8>, 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<T>(&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());
}
}

View File

@ -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}; use super::routes::{auth::models::Credentials, models::Status, users::models::User};
pub mod integrity_verification;
pub mod ldap; pub mod ldap;
pub mod private_key_cache; pub mod private_key_cache;
@ -65,8 +66,10 @@ impl AuthBackend<User> for ApiBackend {
// terminate connection // terminate connection
ldap.unbind().await; ldap.unbind().await;
} else { } else {
argon2::verify_encoded(&user.password, password.as_bytes()) match argon2::verify_encoded(&user.password, password.as_bytes()) {
.map_err(|_| ApiError::InvalidCredentials)?; Ok(true) => {}
_ => return Err(ApiError::InvalidCredentials),
};
} }
Ok(Some(user.clone())) Ok(Some(user.clone()))