sarhash-core 0.1.0

A modular library for password hashing (Argon2) and strength verification (zxcvbn).
Documentation
use argon2::{
    password_hash::{
        rand_core::OsRng,
        PasswordHash, PasswordHasher, PasswordVerifier, SaltString
    },
    Argon2
};
use thiserror::Error;

#[derive(Error, Debug)]
pub enum HasherError {
    #[error("Hashing failed: {0}")]
    HashError(String),
    #[error("Verification failed: {0}")]
    VerifyError(String),
}

/// Hashes a password using Argon2 with a random salt.
pub fn hash_password(password: &str) -> Result<String, HasherError> {
    let salt = SaltString::generate(&mut OsRng);
    let argon2 = Argon2::default();
    
    let password_hash = argon2.hash_password(password.as_bytes(), &salt)
        .map_err(|e| HasherError::HashError(e.to_string()))?;
        
    Ok(password_hash.to_string())
}

/// Verifies a password against a provided hash.
pub fn verify_password(password: &str, hash: &str) -> Result<bool, HasherError> {
    let parsed_hash = PasswordHash::new(hash)
        .map_err(|e| HasherError::VerifyError(e.to_string()))?;
        
    let result = Argon2::default().verify_password(password.as_bytes(), &parsed_hash);
    
    match result {
        Ok(_) => Ok(true),
        Err(argon2::password_hash::Error::Password) => Ok(false),
        Err(e) => Err(HasherError::VerifyError(e.to_string())),
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_hash_and_verify() {
        let password = "my_secure_password";
        let hash = hash_password(password).expect("Hashing should succeed");
        
        assert!(verify_password(password, &hash).expect("Verification should succeed"));
    }

    #[test]
    fn test_verify_fail() {
        let password = "password123";
        let hash = hash_password(password).expect("Hashing should succeed");
        
        assert!(!verify_password("wrong_password", &hash).expect("Verification should succeed"));
    }
}