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}