sha_crypt/
params.rs

1//! Algorithm parameters.
2
3use crate::{Error, Result};
4use core::{
5    default::Default,
6    fmt::{self, Display},
7    str::FromStr,
8};
9
10/// Name of the parameter when serialized in an MCF string.
11const ROUNDS_PARAM: &str = "rounds=";
12
13/// Algorithm parameters.
14#[derive(Clone, Copy, Debug, Eq, PartialEq)]
15pub struct Params {
16    /// Number of times to apply the digest function
17    pub(crate) rounds: u32,
18}
19
20impl Params {
21    /// Default number of rounds.
22    pub const ROUNDS_DEFAULT: u32 = 5_000;
23
24    /// Minimum number of rounds allowed.
25    pub const ROUNDS_MIN: u32 = 1_000;
26
27    /// Maximum number of rounds allowed.
28    pub const ROUNDS_MAX: u32 = 999_999_999;
29
30    /// Create new algorithm parameters.
31    pub fn new(rounds: u32) -> Result<Params> {
32        match rounds {
33            Self::ROUNDS_MIN..=Self::ROUNDS_MAX => Ok(Params { rounds }),
34            _ => Err(Error::RoundsInvalid),
35        }
36    }
37}
38
39impl Default for Params {
40    fn default() -> Self {
41        Params {
42            rounds: Self::ROUNDS_DEFAULT,
43        }
44    }
45}
46
47impl Display for Params {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        write!(f, "rounds={}", self.rounds)
50    }
51}
52
53impl FromStr for Params {
54    type Err = Error;
55
56    fn from_str(s: &str) -> Result<Self> {
57        if s.is_empty() {
58            return Ok(Self::default());
59        }
60
61        if let Some(rounds_str) = s.strip_prefix(ROUNDS_PARAM) {
62            Self::new(rounds_str.parse().map_err(|_| Error::RoundsInvalid)?)
63        } else {
64            Err(Error::ParamsInvalid)
65        }
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::Params;
72
73    #[test]
74    fn test_sha256_crypt_invalid_rounds() {
75        let params = Params::new(Params::ROUNDS_MAX + 1);
76        assert!(params.is_err());
77
78        let params = Params::new(Params::ROUNDS_MIN - 1);
79        assert!(params.is_err());
80    }
81
82    #[test]
83    fn test_sha512_crypt_invalid_rounds() {
84        let params = Params::new(Params::ROUNDS_MAX + 1);
85        assert!(params.is_err());
86
87        let params = Params::new(Params::ROUNDS_MIN - 1);
88        assert!(params.is_err());
89    }
90}