/rust/registry/src/index.crates.io-1949cf8c6b5b557f/password-hash-0.4.2/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, S>(&self, password: &[u8], salt: &'a S) -> Result<PasswordHash<'a>> |
34 | 0 | where |
35 | 0 | S: AsRef<str> + ?Sized, |
36 | | { |
37 | 0 | self.hash_password_customized( |
38 | 0 | password, |
39 | 0 | None, |
40 | 0 | None, |
41 | 0 | Self::Params::default(), |
42 | 0 | Salt::try_from(salt.as_ref())?, |
43 | | ) |
44 | 0 | } |
45 | | } |
46 | | |
47 | | /// Trait for password verification. |
48 | | /// |
49 | | /// Automatically impl'd for any type that impls [`PasswordHasher`]. |
50 | | /// |
51 | | /// This trait is object safe and can be used to implement abstractions over |
52 | | /// multiple password hashing algorithms. One such abstraction is provided by |
53 | | /// the [`PasswordHash::verify_password`] method. |
54 | | pub trait PasswordVerifier { |
55 | | /// Compute this password hashing function against the provided password |
56 | | /// using the parameters from the provided password hash and see if the |
57 | | /// computed output matches. |
58 | | fn verify_password(&self, password: &[u8], hash: &PasswordHash<'_>) -> Result<()>; |
59 | | } |
60 | | |
61 | | impl<T: PasswordHasher> PasswordVerifier for T { |
62 | 0 | fn verify_password(&self, password: &[u8], hash: &PasswordHash<'_>) -> Result<()> { |
63 | 0 | if let (Some(salt), Some(expected_output)) = (&hash.salt, &hash.hash) { |
64 | 0 | let computed_hash = self.hash_password_customized( |
65 | 0 | password, |
66 | 0 | Some(hash.algorithm), |
67 | 0 | hash.version, |
68 | 0 | T::Params::try_from(hash)?, |
69 | 0 | *salt, |
70 | 0 | )?; |
71 | | |
72 | 0 | if let Some(computed_output) = &computed_hash.hash { |
73 | | // See notes on `Output` about the use of a constant-time comparison |
74 | 0 | if expected_output == computed_output { |
75 | 0 | return Ok(()); |
76 | 0 | } |
77 | 0 | } |
78 | 0 | } |
79 | | |
80 | 0 | Err(Error::Password) |
81 | 0 | } |
82 | | } |
83 | | |
84 | | /// Trait for password hashing algorithms which support the legacy |
85 | | /// [Modular Crypt Format (MCF)][MCF]. |
86 | | /// |
87 | | /// [MCF]: https://passlib.readthedocs.io/en/stable/modular_crypt_format.html |
88 | | pub trait McfHasher { |
89 | | /// Upgrade an MCF hash to a PHC hash. MCF follow this rough format: |
90 | | /// |
91 | | /// ```text |
92 | | /// $<id>$<content> |
93 | | /// ``` |
94 | | /// |
95 | | /// MCF hashes are otherwise largely unstructured and parsed according to |
96 | | /// algorithm-specific rules so hashers must parse a raw string themselves. |
97 | | fn upgrade_mcf_hash<'a>(&self, hash: &'a str) -> Result<PasswordHash<'a>>; |
98 | | |
99 | | /// Verify a password hash in MCF format against the provided password. |
100 | 0 | fn verify_mcf_hash(&self, password: &[u8], mcf_hash: &str) -> Result<()> |
101 | 0 | where |
102 | 0 | Self: PasswordVerifier, |
103 | | { |
104 | 0 | self.verify_password(password, &self.upgrade_mcf_hash(mcf_hash)?) |
105 | 0 | } |
106 | | } |