diff --git a/dpts-server/Cargo.toml b/dpts-server/Cargo.toml index 1e84f74..d07ce25 100644 --- a/dpts-server/Cargo.toml +++ b/dpts-server/Cargo.toml @@ -6,11 +6,13 @@ edition.workspace = true repository.workspace = true [dependencies] +argon2 = "0.5.3" +axum = "0.8.4" +clap = {workspace = true, features = ["derive"]} dpts-core = {workspace = true} chrono = {workspace = true} -clap = {workspace = true, features = ["derive"]} -axum = "0.8.4" serde.workspace = true thiserror.workspace = true tokio.workspace = true toml.workspace = true +rand = "0.9.1" diff --git a/dpts-server/src/auth.rs b/dpts-server/src/auth.rs new file mode 100644 index 0000000..7e9f3c4 --- /dev/null +++ b/dpts-server/src/auth.rs @@ -0,0 +1,45 @@ +use argon2::{ + Argon2, + PasswordHasher, + PasswordVerifier, + password_hash::{ + Salt, + SaltString, + PasswordHash, + rand_core::OsRng, + }, +}; +use chrono::format::parse; +use crate::error::Error; +use tokio::sync::OnceCell; + +pub fn try_hash_password(password: &str) -> Result { + let mut rng = OsRng::default(); + let salt_string= SaltString::generate(&mut rng); + let salt = salt_string.as_salt(); + let hash = Argon2::default().hash_password(password.as_bytes(), salt).or(Err(Error::PasswordHash("Hashing password with salt".to_string())))?; + Ok(hash.to_string()) +} + +pub fn try_verify_password(password: &str, password_hash: &str) -> Result { + let parsed_hash = PasswordHash::new(password_hash).or(Err(Error::PasswordHash("Failed to parse password hash string".to_string())))?; + match Argon2::default().verify_password(password.as_bytes(), &parsed_hash) { + Ok(_) => Ok(true), + Err(_) => Ok(false), + } +} + +#[cfg(test)] +mod tests { + use argon2::password_hash::rand_core::OsRng; + + use super::*; + #[test] + fn test_password() { + let valid_password = "valid"; + let invalid_password = "invalid"; + let hash = try_hash_password(valid_password).unwrap(); + assert!(try_verify_password(valid_password, &hash).unwrap()); + assert!(!try_verify_password(invalid_password, &hash).unwrap()); + } +} \ No newline at end of file diff --git a/dpts-server/src/error.rs b/dpts-server/src/error.rs index 1c8363f..c1339a2 100644 --- a/dpts-server/src/error.rs +++ b/dpts-server/src/error.rs @@ -1,7 +1,11 @@ #[derive(thiserror::Error, Debug)] pub enum Error { + #[error("Uninitialized OnceCell: {0}")] + UninitializedOnceCell(String), #[error("Parse int error")] ParseInt(#[from] std::num::ParseIntError), + #[error("Argon2 Password hash error: {0}")] + PasswordHash(String), #[error("Parse toml error")] TomlDe(#[from] toml::de::Error), #[error("Missing config value: ({0})")] diff --git a/dpts-server/src/lib.rs b/dpts-server/src/lib.rs index a31209e..0aeb816 100644 --- a/dpts-server/src/lib.rs +++ b/dpts-server/src/lib.rs @@ -1,4 +1,5 @@ mod args; +mod auth; mod config; pub mod error; pub use args::Args; \ No newline at end of file