From f754e472212c120325d7086f6a020a8a1fda5ff5 Mon Sep 17 00:00:00 2001 From: jakubmanczak Date: Sat, 28 Feb 2026 00:23:15 +0100 Subject: [PATCH] centralize Argon2 setup --- src/main.rs | 1 + src/users/auth/implementation.rs | 24 +++++++----------------- src/users/auth/mod.rs | 19 ++++++++++++++++--- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/main.rs b/src/main.rs index 5f64a2f..5e5829e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,7 @@ async fn main() -> Result<(), Box> { } database::migrations()?; + users::auth::init_password_dummies(); users::setup::initialise_reserved_users_if_needed()?; let port = match std::env::var("PORT") { diff --git a/src/users/auth/implementation.rs b/src/users/auth/implementation.rs index c2cca0b..63a52d7 100644 --- a/src/users/auth/implementation.rs +++ b/src/users/auth/implementation.rs @@ -1,4 +1,4 @@ -use argon2::{Argon2, PasswordHash, PasswordHasher, PasswordVerifier, password_hash::SaltString}; +use argon2::{PasswordHash, PasswordHasher, PasswordVerifier, password_hash::SaltString}; use axum::{ http::{ HeaderMap, StatusCode, @@ -15,8 +15,9 @@ use crate::{ users::{ User, auth::{ - AuthError, COOKIE_NAME, SessionAuthRequired, SessionAuthenticate, TokenSize, - UserAuthDummyData, UserAuthRequired, UserAuthenticate, UserPasswordHashing, + AuthError, COOKIE_NAME, DUMMY_PASSWORD, DUMMY_PASSWORD_PHC, SHARED_ARGON, + SessionAuthRequired, SessionAuthenticate, TokenSize, UserAuthRequired, + UserAuthenticate, UserPasswordHashing, }, sessions::Session, }, @@ -75,29 +76,18 @@ impl SessionAuthRequired for Option { impl UserPasswordHashing for User { fn hash_password(passw: &str) -> Result { use rand08::rngs::OsRng as ArgonOsRng; - let argon = Argon2::default(); let passw = passw.as_bytes(); let salt = SaltString::generate(&mut ArgonOsRng); - Ok(argon.hash_password(passw, &salt)?.to_string()) + Ok(SHARED_ARGON.hash_password(passw, &salt)?.to_string()) } fn match_hash_password(passw: &str, hash: &str) -> Result { - let argon = Argon2::default(); let passw = passw.as_bytes(); let hash = PasswordHash::try_from(hash)?; - Ok(argon.verify_password(passw, &hash).is_ok()) + Ok(SHARED_ARGON.verify_password(passw, &hash).is_ok()) } } -// TODO: generate these at startup using predefined Argon2 params if -// these ever change from ::Default - the PHC must have the same factors as real hashes. -impl UserAuthDummyData for User { - /// This PHC generated for b"password" - const DUMMY_PASSWORD_PHC: &str = "$argon2id$v=19$m=19456,t=2,p=1$PXcTKpFhLRB70fVF35XYDQ$QOW2IxdPUvqD38+ScqX5SgO+jwweaMO9DUGqmkTeofQ"; - /// Different than the input password of the PHC - const DUMMY_PASSWORD: &str = "different_password"; -} - impl From for AuthError { fn from(err: argon2::password_hash::Error) -> Self { AuthError::PassHashError(err) @@ -213,7 +203,7 @@ pub fn authenticate_via_credentials( false => Err(AuthError::InvalidCredentials), }, _ => { - let _ = User::match_hash_password(User::DUMMY_PASSWORD, User::DUMMY_PASSWORD_PHC)?; + let _ = User::match_hash_password(DUMMY_PASSWORD, &*DUMMY_PASSWORD_PHC)?; Err(AuthError::InvalidCredentials) } } diff --git a/src/users/auth/mod.rs b/src/users/auth/mod.rs index 53cd935..89cb6b9 100644 --- a/src/users/auth/mod.rs +++ b/src/users/auth/mod.rs @@ -1,3 +1,6 @@ +use std::sync::LazyLock; + +use argon2::{Argon2, PasswordHasher, password_hash::SaltString}; use axum::http::HeaderMap; use rand08::{RngCore, rngs::OsRng}; @@ -29,9 +32,19 @@ pub trait UserPasswordHashing { /// Returns whether the password matches the hash fn match_hash_password(passw: &str, hash: &str) -> Result; } -pub trait UserAuthDummyData { - const DUMMY_PASSWORD_PHC: &str; - const DUMMY_PASSWORD: &str; + +pub static SHARED_ARGON: LazyLock = LazyLock::new(|| Argon2::default()); +pub const DUMMY_PASSWORD: &str = "PASSWORD"; +pub static DUMMY_PASSWORD_PHC: LazyLock = LazyLock::new(|| { + let salt = SaltString::generate(&mut OsRng); + SHARED_ARGON + .hash_password(DUMMY_PASSWORD.as_bytes(), &salt) + .unwrap() + .to_string() +}); +pub fn init_password_dummies() { + let _ = &*DUMMY_PASSWORD_PHC; + println!("Password hashing setup finished"); } #[derive(thiserror::Error, Debug)]