age_plugin_argon2/
params.rs1use std::fmt;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Deserialize)]
7struct Argon2ParamsRaw {
8 m_cost: u32,
9 t_cost: u32,
10 p_cost: u32,
11}
12
13impl TryFrom<Argon2ParamsRaw> for Argon2Params {
14 type Error = InvalidParams;
15
16 fn try_from(raw: Argon2ParamsRaw) -> Result<Self, Self::Error> {
17 Self::new(raw.m_cost, raw.t_cost, raw.p_cost)
18 }
19}
20
21#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
23#[serde(try_from = "Argon2ParamsRaw")]
24pub struct Argon2Params {
25 m_cost: u32,
27 t_cost: u32,
29 p_cost: u32,
31}
32
33#[derive(Debug, thiserror::Error)]
35#[error("invalid Argon2 parameters: {reason}")]
36pub struct InvalidParams {
37 reason: String,
38}
39
40impl Argon2Params {
41 pub fn new(m_cost: u32, t_cost: u32, p_cost: u32) -> Result<Self, InvalidParams> {
48 argon2::Params::new(m_cost, t_cost, p_cost, Some(32)).map_err(|e| InvalidParams {
51 reason: e.to_string(),
52 })?;
53
54 Ok(Self {
55 m_cost,
56 t_cost,
57 p_cost,
58 })
59 }
60
61 pub fn m_cost(&self) -> u32 {
63 self.m_cost
64 }
65
66 pub fn t_cost(&self) -> u32 {
68 self.t_cost
69 }
70
71 pub fn p_cost(&self) -> u32 {
73 self.p_cost
74 }
75}
76
77impl fmt::Debug for Argon2Params {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 f.debug_struct("Argon2Params")
80 .field("m_cost", &self.m_cost)
81 .field("t_cost", &self.t_cost)
82 .field("p_cost", &self.p_cost)
83 .finish()
84 }
85}
86
87impl Default for Argon2Params {
89 fn default() -> Self {
90 Self {
92 m_cost: 65536,
93 t_cost: 3,
94 p_cost: 4,
95 }
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn test_default_params_are_valid() {
105 let p = Argon2Params::default();
106 assert_eq!(p.m_cost(), 65536);
107 assert_eq!(p.t_cost(), 3);
108 assert_eq!(p.p_cost(), 4);
109 }
110
111 #[test]
112 fn test_valid_params() {
113 let p = Argon2Params::new(256, 1, 1).unwrap();
114 assert_eq!(p.m_cost(), 256);
115 }
116
117 #[test]
118 fn test_zero_t_cost_rejected() {
119 assert!(Argon2Params::new(256, 0, 1).is_err());
120 }
121
122 #[test]
123 fn test_zero_p_cost_rejected() {
124 assert!(Argon2Params::new(256, 1, 0).is_err());
125 }
126
127 #[test]
128 fn test_m_cost_too_low_rejected() {
129 assert!(Argon2Params::new(1, 1, 1).is_err());
131 }
132}