1use log::{info, debug};
2
3#[cfg(feature = "rust-argon2")]
4use ::argon2::{Config, Variant, Version};
5#[cfg(feature = "argonautica")]
6use argonautica::{
7 config::{Variant, Version},
8 Hasher,
9};
10#[cfg(feature = "argon2-kdf")]
11use argon2_kdf::{Hasher, Algorithm};
12#[cfg(feature = "argon2")]
13use ::argon2::{Argon2, Algorithm, Version, ParamsBuilder};
14
15use crate::utils::{unmake_u32, unmake_u64};
16use super::*;
17
18const _DEFAULT_ITERATIONS: u64 = 2;
20const _DEFAULT_MEMORY: u64 = 1024 * 1024;
21const _DEFAULT_PARALLELISM: u32 = 2;
22
23#[cfg(feature = "rust-argon2")]
24fn transform_argon2_lib(
25 composite_key: &[u8],
26 salt: &[u8],
27 version: u32,
28 mem_cost: u32,
29 time_cost: u32,
30 lanes: u32,
31) -> io::Result<Vec<u8>> {
32 debug!("Rust Argon2");
33 let version = match version {
34 0x13 => Version::Version13,
35 0x10 => Version::Version10,
36 _ => {
37 panic!("Misconfigured!");
38 }
39 };
40 let config = Config {
41 variant: Variant::Argon2d,
42 version,
43 mem_cost,
44 time_cost,
45 lanes,
46 secret: &[],
47 ad: &[],
48 hash_length: 32,
49 };
50 let hash = ::argon2::hash_raw(composite_key, salt, &config).unwrap();
51 println!(
52 "P: {:0x?}, S: {:0x?}, H: {:0x?}, C: {:#?}",
53 composite_key, salt, hash, config
54 );
55 Ok(hash)
56}
57
58#[cfg(feature = "argonautica")]
59fn transform_argon2_lib(
60 composite_key: &[u8],
61 salt: &[u8],
62 version: u32,
63 mem_cost: u32,
64 time_cost: u32,
65 lanes: u32,
66) -> io::Result<Vec<u8>> {
67 debug!("Argonautica");
68 let version = match version {
69 0x13 => Version::_0x13,
70 0x10 => Version::_0x10,
71 _ => {
72 panic!("Misconfigured!");
73 }
74 };
75 let mut hasher = Hasher::default();
76 hasher
77 .configure_iterations(time_cost)
78 .configure_lanes(lanes)
79 .configure_memory_size(mem_cost)
80 .configure_variant(Variant::Argon2d)
81 .configure_version(version)
82 .opt_out_of_secret_key(true);
83 Ok(hasher
85 .with_password(composite_key)
86 .with_salt(salt)
87 .hash_raw()
88 .unwrap()
89 .raw_hash_bytes()
90 .to_owned())
91}
92
93#[cfg(feature = "argon2-kdf")]
94fn transform_argon2_lib(
95 composite_key: &[u8],
96 salt: &[u8],
97 version: u32,
98 mem_cost: u32,
99 time_cost: u32,
100 lanes: u32,
101) -> io::Result<Vec<u8>> {
102 debug!("Argon2-KDF");
103 Ok(Hasher::new()
104 .algorithm(Algorithm::Argon2d)
105 .custom_salt(salt)
106 .hash_length(32)
107 .iterations(time_cost)
108 .memory_cost_kib(mem_cost)
109 .threads(lanes)
110 .hash(composite_key)
111 .unwrap()
112 .as_bytes()
113 .to_owned())
114}
115
116#[cfg(feature = "argon2")]
117fn transform_argon2_lib(
118 composite_key: &[u8],
119 salt: &[u8],
120 version: u32,
121 mem_cost: u32,
122 time_cost: u32,
123 lanes: u32,
124) -> io::Result<Vec<u8>> {
125 debug!("Argon2");
126 let version = match version {
127 0x13 => Version::V0x13,
128 0x10 => Version::V0x10,
129 _ => {
130 panic!("Misconfigured!");
131 }
132 };
133 let mut hash = [0; 32];
134 Argon2::new(Algorithm::Argon2d, version, ParamsBuilder::new()
135 .m_cost(mem_cost)
136 .t_cost(time_cost)
137 .p_cost(lanes)
138 .output_len(32)
139 .build()
140 .unwrap()
141 ).hash_password_into(composite_key, &salt, &mut hash).unwrap();
142 Ok(hash.to_vec())
143}
144
145#[cfg(any(feature = "rust-argon2", feature = "argonautica", feature = "argon2-kdf", feature = "argon2"))]
146pub fn transform_argon2(
147 composite_key: &[u8],
148 custom_data: &HashMap<String, Vec<u8>>,
149) -> io::Result<Vec<u8>> {
150 info!("Found Argon2 KDF");
151 let salt = match custom_data.get(KDF_PARAM_SALT) {
152 Some(x) => x,
153 None => {
154 return Err(io::Error::new(io::ErrorKind::Other, "Argon2 salt missing"));
155 }
156 };
157 let version = match custom_data.get(KDF_PARAM_VERSION) {
158 Some(x) => match unmake_u32(x) {
159 Some(x) if x > 0x13 => {
160 println!("Version: {}", x);
161 return Err(io::Error::new(
162 io::ErrorKind::Other,
163 "Argon2 version too new",
164 ));
165 }
166 Some(x) if x == 0x13 => 0x13,
167 Some(x) if x >= 0x10 => 0x10,
168 Some(_) => {
169 return Err(io::Error::new(
170 io::ErrorKind::Other,
171 "Argon2 version too old",
172 ));
173 }
174 None => {
175 return Err(io::Error::new(io::ErrorKind::Other, "Invalid version"));
176 }
177 },
178 None => {
179 return Err(io::Error::new(
180 io::ErrorKind::Other,
181 "Argon2 version missing",
182 ));
183 }
184 };
185 let mem_cost = match custom_data.get(KDF_PARAM_MEMORY) {
186 Some(x) => match unmake_u64(x) {
187 Some(x) => x / 1024,
188 None => {
189 return Err(io::Error::new(
190 io::ErrorKind::Other,
191 "Invalid memory parameter",
192 ));
193 }
194 },
195 None => {
196 return Err(io::Error::new(
197 io::ErrorKind::Other,
198 "Argon2 memory parameter missing",
199 ));
200 }
201 };
202 let time_cost = match custom_data.get(KDF_PARAM_ITERATIONS) {
203 Some(x) => match unmake_u64(x) {
204 Some(x) => x,
205 None => {
206 return Err(io::Error::new(
207 io::ErrorKind::Other,
208 "Invalid time parameter",
209 ));
210 }
211 },
212 None => {
213 return Err(io::Error::new(
214 io::ErrorKind::Other,
215 "Argon2 time parameter missing",
216 ));
217 }
218 };
219 let lanes = match custom_data.get(KDF_PARAM_PARALLELISM) {
220 Some(x) => match unmake_u32(x) {
221 Some(x) => x,
222 None => {
223 return Err(io::Error::new(
224 io::ErrorKind::Other,
225 "Invalid parallelism parameter",
226 ));
227 }
228 },
229 None => {
230 return Err(io::Error::new(
231 io::ErrorKind::Other,
232 "Argon2 parallelism parameter missing",
233 ));
234 }
235 };
236 let hash = transform_argon2_lib(
237 composite_key,
238 salt,
239 version,
240 mem_cost as u32,
241 time_cost as u32,
242 lanes,
243 )
244 .unwrap();
245 Ok(hash)
246}
247
248#[cfg(not(any(feature = "rust-argon2", feature = "argonautica", feature = "argon2-kdf", feature = "argon2")))]
249pub fn transform_argon2(
250 _composite_key: &[u8],
251 custom_data: &HashMap<String, Vec<u8>>,
252) -> io::Result<Vec<u8>> {
253 Err(io::Error::new(io::ErrorKind::Other, "Argon2 unimplemented"))
254}