askar_crypto/kdf/
argon2.rs1pub use argon2::{Algorithm, Version};
4
5use super::KeyDerivation;
6use crate::{
7 error::Error,
8 generic_array::typenum::{Unsigned, U16},
9};
10
11pub type SaltSize = U16;
13
14pub const SALT_LENGTH: usize = SaltSize::USIZE;
16
17pub const PARAMS_INTERACTIVE: Params = Params {
19 alg: Algorithm::Argon2i,
20 version: Version::V0x13,
21 mem_cost: 32768,
22 time_cost: 4,
23};
24pub const PARAMS_MODERATE: Params = Params {
26 alg: Algorithm::Argon2i,
27 version: Version::V0x13,
28 mem_cost: 131072,
29 time_cost: 6,
30};
31
32#[derive(Clone, Copy, Debug, PartialEq, Eq)]
34pub struct Params {
35 alg: Algorithm,
36 version: Version,
37 mem_cost: u32,
38 time_cost: u32,
39}
40
41#[derive(Debug)]
43pub struct Argon2<'a> {
44 password: &'a [u8],
45 salt: &'a [u8],
46 params: Params,
47}
48
49impl<'a> Argon2<'a> {
50 pub fn new(password: &'a [u8], salt: &'a [u8], params: Params) -> Result<Self, Error> {
52 if salt.len() < SALT_LENGTH {
53 return Err(err_msg!(Usage, "Invalid salt for argon2i hash"));
54 }
55 Ok(Self {
56 password,
57 salt,
58 params,
59 })
60 }
61}
62
63impl KeyDerivation for Argon2<'_> {
64 fn derive_key_bytes(&mut self, key_output: &mut [u8]) -> Result<(), Error> {
65 if key_output.len() > u32::MAX as usize {
66 return Err(err_msg!(
67 Usage,
68 "Output length exceeds max for argon2i hash"
69 ));
70 }
71 let mut pbuild = argon2::ParamsBuilder::new();
72 pbuild
73 .m_cost(self.params.mem_cost)
74 .t_cost(self.params.time_cost);
75 argon2::Argon2::new(
76 self.params.alg,
77 self.params.version,
78 pbuild.build().unwrap(),
79 )
80 .hash_password_into(self.password, self.salt, key_output)
81 .map_err(|_| err_msg!(Unexpected, "Error deriving key"))
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn expected() {
91 let pass = b"my password";
92 let salt = b"long enough salt";
93 let mut output = [0u8; 32];
94 Argon2::new(pass, salt, PARAMS_INTERACTIVE)
95 .unwrap()
96 .derive_key_bytes(&mut output)
97 .unwrap();
98 assert_eq!(
99 output,
100 hex!("9ef87bcf828c46c0136a0d1d9e391d713f75b327c6dc190455bd36c1bae33259")
101 );
102 }
103}