Coverage Report

Created: 2026-03-31 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/password-hash-0.5.0/src/traits.rs
Line
Count
Source
1
//! Trait definitions.
2
3
use crate::{Decimal, Error, Ident, ParamsString, PasswordHash, Result, Salt};
4
use core::fmt::Debug;
5
6
/// Trait for password hashing functions.
7
pub trait PasswordHasher {
8
    /// Algorithm-specific parameters.
9
    type Params: Clone
10
        + Debug
11
        + Default
12
        + for<'a> TryFrom<&'a PasswordHash<'a>, Error = Error>
13
        + TryInto<ParamsString, Error = Error>;
14
15
    /// Compute a [`PasswordHash`] from the provided password using an
16
    /// explicit set of customized algorithm parameters as opposed to the
17
    /// defaults.
18
    ///
19
    /// When in doubt, use [`PasswordHasher::hash_password`] instead.
20
    fn hash_password_customized<'a>(
21
        &self,
22
        password: &[u8],
23
        algorithm: Option<Ident<'a>>,
24
        version: Option<Decimal>,
25
        params: Self::Params,
26
        salt: impl Into<Salt<'a>>,
27
    ) -> Result<PasswordHash<'a>>;
28
29
    /// Simple API for computing a [`PasswordHash`] from a password and
30
    /// salt value.
31
    ///
32
    /// Uses the default recommended parameters for a given algorithm.
33
0
    fn hash_password<'a>(
34
0
        &self,
35
0
        password: &[u8],
36
0
        salt: impl Into<Salt<'a>>,
37
0
    ) -> Result<PasswordHash<'a>> {
38
0
        self.hash_password_customized(password, None, None, Self::Params::default(), salt)
39
0
    }
Unexecuted instantiation: <pbkdf2::simple::Pbkdf2 as password_hash::traits::PasswordHasher>::hash_password::<&password_hash::salt::SaltString>
Unexecuted instantiation: <scrypt::simple::Scrypt as password_hash::traits::PasswordHasher>::hash_password::<&password_hash::salt::SaltString>
Unexecuted instantiation: <_ as password_hash::traits::PasswordHasher>::hash_password::<_>
40
}
41
42
/// Trait for password verification.
43
///
44
/// Automatically impl'd for any type that impls [`PasswordHasher`].
45
///
46
/// This trait is object safe and can be used to implement abstractions over
47
/// multiple password hashing algorithms. One such abstraction is provided by
48
/// the [`PasswordHash::verify_password`] method.
49
pub trait PasswordVerifier {
50
    /// Compute this password hashing function against the provided password
51
    /// using the parameters from the provided password hash and see if the
52
    /// computed output matches.
53
    fn verify_password(&self, password: &[u8], hash: &PasswordHash<'_>) -> Result<()>;
54
}
55
56
impl<T: PasswordHasher> PasswordVerifier for T {
57
0
    fn verify_password(&self, password: &[u8], hash: &PasswordHash<'_>) -> Result<()> {
58
0
        if let (Some(salt), Some(expected_output)) = (&hash.salt, &hash.hash) {
59
0
            let computed_hash = self.hash_password_customized(
60
0
                password,
61
0
                Some(hash.algorithm),
62
0
                hash.version,
63
0
                T::Params::try_from(hash)?,
64
0
                *salt,
65
0
            )?;
66
67
0
            if let Some(computed_output) = &computed_hash.hash {
68
                // See notes on `Output` about the use of a constant-time comparison
69
0
                if expected_output == computed_output {
70
0
                    return Ok(());
71
0
                }
72
0
            }
73
0
        }
74
75
0
        Err(Error::Password)
76
0
    }
Unexecuted instantiation: <argon2::Argon2 as password_hash::traits::PasswordVerifier>::verify_password
Unexecuted instantiation: <_ as password_hash::traits::PasswordVerifier>::verify_password
77
}
78
79
/// Trait for password hashing algorithms which support the legacy
80
/// [Modular Crypt Format (MCF)][MCF].
81
///
82
/// [MCF]: https://passlib.readthedocs.io/en/stable/modular_crypt_format.html
83
pub trait McfHasher {
84
    /// Upgrade an MCF hash to a PHC hash. MCF follow this rough format:
85
    ///
86
    /// ```text
87
    /// $<id>$<content>
88
    /// ```
89
    ///
90
    /// MCF hashes are otherwise largely unstructured and parsed according to
91
    /// algorithm-specific rules so hashers must parse a raw string themselves.
92
    fn upgrade_mcf_hash<'a>(&self, hash: &'a str) -> Result<PasswordHash<'a>>;
93
94
    /// Verify a password hash in MCF format against the provided password.
95
0
    fn verify_mcf_hash(&self, password: &[u8], mcf_hash: &str) -> Result<()>
96
0
    where
97
0
        Self: PasswordVerifier,
98
    {
99
0
        self.verify_password(password, &self.upgrade_mcf_hash(mcf_hash)?)
100
0
    }
101
}