argon2_async/
config.rs

1use argon2::{Algorithm, Version};
2use once_cell::sync::OnceCell;
3
4pub(crate) static GLOBAL_CONFIG: OnceCell<tokio::sync::RwLock<Config>> = OnceCell::new();
5
6/// Set the global config.
7pub async fn set_config(config: Config<'static>) {
8    match GLOBAL_CONFIG.get() {
9        Some(cfg) => {
10            let mut cfg = cfg.write().await;
11            *cfg = config;
12        }
13        None => assert!(GLOBAL_CONFIG.set(tokio::sync::RwLock::new(config)).is_ok()),
14    }
15}
16
17/// Configuration for the `argon2` algorithm.
18pub struct Config<'k> {
19    /// Set the hashing algorithm in use.
20    ///
21    /// According to the [latest (as of 5/18) Argon2 RFC](https://tools.ietf.org/html/draft-irtf-cfrg-argon2-03) ...
22    /// "Argon2 has one primary variant: Argon2id, and two supplementary
23    /// variants: Argon2d and Argon2i. Argon2d uses data-dependent memory
24    /// access, which makes it suitable for ... applications with no threats from
25    /// side-channel timing attacks. Argon2i uses data-independent memory access,
26    /// which is preferred for password hashing and password-based key derivation.
27    /// Argon2id works as Argon2i for the first half of the first iteration over the memory,
28    /// and as Argon2d for the rest, thus providing both side-channel attack
29    pub algorithm: Algorithm,
30    /// Set the version of `argon2` to use.
31    pub version: Version,
32    /// The secret key to use.
33    ///
34    /// This is **strongly** recommended in production.
35    pub secret_key: Option<&'k [u8]>,
36    /// The memory cost of the algorithm in kilobytes.
37    ///
38    /// Argon2 has a notion of "memory size" or "memory cost" (in kilobytes). All else equal
39    /// and generally speaking, the greater the memory cost, the longer it takes to perform
40    /// the hash and the more secure the resulting hash. More memory cost basically means
41    /// more memory used. This and "iterations" are, generally speaking, the two parameters
42    /// to adjust in order to increase or decrease the security of your hash. If you're going
43    /// to use this crate in production, you should probably tweak this parameter (and the
44    /// iterations parameter) in order to increase the time it takes to hash to the maximum
45    /// you can reasonably allow for your use-case (e.g. to probably about 300-500 milliseconds
46    /// for the use-case of hashing user passwords for a website).
47    pub memory_cost: u32,
48    /// The number of iterations to use.
49    ///
50    /// Argon2 has a notion of "iterations" or "time cost". All else equal and generally
51    /// speaking, the greater the number of iterations, the longer it takes to perform the
52    /// hash and the more secure the resulting hash. More iterations basically means more
53    /// CPU load. This and "memory cost" are the two primary parameters to adjust in order
54    /// to increase or decrease the security of your hash. If you're going to use this
55    /// crate in production, you should probably tweak this parameter (and the memory cost
56    /// parameter) in order to increase the time it takes to hash to the maximum you can
57    /// reasonably allow for your use-case (e.g. to probably about 300-500 milliseconds for
58    /// the use-case of hashing user passwords for a website).
59    pub iterations: u32,
60    /// The parallelism of the algorithm.
61    ///
62    /// Argon2 can break up its work into one or more "lanes" during some parts of the
63    /// hashing algorithm. If you configure it with multiple lanes, the hashing algorithm
64    /// will perform its work in parallel in some parts, potentially speeding up the time
65    /// it takes to produce a hash without diminishing the security of the result.
66    pub parallelism: u32,
67    /// The output length of the algorithm in bytes.
68    pub output_length: Option<usize>,
69}
70
71impl<'k> Default for Config<'k> {
72    /// Create a new default config. This is good for basic purposes,
73    /// but **SHOULD NOT** be used in a production environment.
74    ///
75    /// * Algorithm: Argon2id
76    /// * Version: 19 (0x13)
77    /// * Secret key: None,
78    /// * Memory size: 4,096 kilobytes
79    /// * Iterations: 3
80    /// * Parallelism: 1
81    /// * Output length: Some(32)
82    #[inline]
83    fn default() -> Self {
84        Self {
85            algorithm: Algorithm::Argon2id,
86            version: Version::V0x13,
87            secret_key: None,
88            memory_cost: 512,
89            iterations: 3,
90            parallelism: 1,
91            output_length: Some(32),
92        }
93    }
94}
95
96impl<'k> Config<'k> {
97    /// Create a new config. This is an insecure config and **should not be used in production**!
98    #[inline]
99    pub fn new_insecure() -> Self {
100        Self::default()
101    }
102
103    /// Create a new config. This config is somewhat more secure than `new_insecure()` but a secret key should still be set with the `set_secret_key()` function.
104    #[inline]
105    pub fn new() -> Self {
106        Self {
107            memory_cost: 8192,
108            iterations: 200,
109            parallelism: num_cpus::get_physical() as u32,
110            ..Self::default()
111        }
112    }
113}
114
115impl<'k> Config<'k> {
116    /// Set the hashing algorithm in use.
117    ///
118    /// The default (Argon2id) should be fine for most uses.
119    #[inline]
120    pub fn set_algorithm(&mut self, algorithm: Algorithm) -> &mut Self {
121        self.algorithm = algorithm;
122        self
123    }
124
125    /// Set the version of `argon2` to use.
126    ///
127    /// The default (0x13 or v19) should be fine for most uses.
128    #[inline]
129    pub fn set_version(&mut self, version: Version) -> &mut Self {
130        self.version = version;
131        self
132    }
133
134    /// Set the secret key to use. This is **strongly** recommended in a production environment.
135    #[inline]
136    pub fn set_secret_key(&mut self, secret_key: Option<&'k [u8]>) -> &mut Self {
137        self.secret_key = secret_key;
138        self
139    }
140
141    /// Set the memory cost in kilobytes.
142    ///
143    /// Default: 512 for insecure, and 4,096 for secure.
144    #[inline]
145    pub fn set_memory_cost(&mut self, memory_cost: u32) -> &mut Self {
146        self.memory_cost = memory_cost;
147        self
148    }
149
150    /// Set the number of iterations to use.
151    ///
152    /// Default: 3 for insecure, and 200 for secure.
153    #[inline]
154    pub fn set_iterations(&mut self, iterations: u32) -> &mut Self {
155        self.iterations = iterations;
156        self
157    }
158
159    /// Set the parallelism of the algorithm.
160    ///
161    /// Default: 1 for insecure, and the number of physical CPU cores on the host for secure.
162    #[inline]
163    pub fn set_parallelism(&mut self, parallelism: u32) -> &mut Self {
164        self.parallelism = parallelism;
165        self
166    }
167
168    /// Set the output length of the algorithm in bytes.
169    ///
170    /// Default: 32
171    #[inline]
172    pub fn set_output_length(&mut self, output_length: Option<usize>) -> &mut Self {
173        self.output_length = output_length;
174        self
175    }
176}