use argon2::{Algorithm, Argon2, Params, Version};
pub fn key<const N: usize>(
password: &[u8],
salt: &[u8],
time: u32,
memory: u32,
threads: u32,
) -> [u8; N] {
let params = Params::new(memory, time, threads, Some(N)).unwrap();
let argon2 = Argon2::new(Algorithm::Argon2id, Version::V0x13, params);
let mut output = [0u8; N];
argon2
.hash_password_into(password, salt, &mut output)
.unwrap();
output
}
pub fn key_with_len(
password: &[u8],
salt: &[u8],
time: u32,
memory: u32,
threads: u32,
out: usize,
) -> Vec<u8> {
let params = Params::new(memory, time, threads, Some(out)).unwrap();
let argon2 = Argon2::new(Algorithm::Argon2id, Version::V0x13, params);
let mut output = vec![0u8; out];
argon2
.hash_password_into(password, salt, &mut output)
.unwrap();
output
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_argon2id_vectors() {
struct TestCase {
time: u32,
memory: u32,
threads: u32,
hash: &'static str,
}
let tests = [
TestCase {
time: 1,
memory: 64,
threads: 1,
hash: "655ad15eac652dc59f7170a7332bf49b8469be1fdb9c28bb",
},
TestCase {
time: 2,
memory: 64,
threads: 1,
hash: "068d62b26455936aa6ebe60060b0a65870dbfa3ddf8d41f7",
},
TestCase {
time: 2,
memory: 64,
threads: 2,
hash: "350ac37222f436ccb5c0972f1ebd3bf6b958bf2071841362",
},
TestCase {
time: 3,
memory: 256,
threads: 2,
hash: "4668d30ac4187e6878eedeacf0fd83c5a0a30db2cc16ef0b",
},
TestCase {
time: 4,
memory: 4096,
threads: 4,
hash: "145db9733a9f4ee43edf33c509be96b934d505a4efb33c5a",
},
TestCase {
time: 4,
memory: 1024,
threads: 8,
hash: "8dafa8e004f8ea96bf7c0f93eecf67a6047476143d15577f",
},
TestCase {
time: 2,
memory: 64,
threads: 3,
hash: "4a15b31aec7c2590b87d1f520be7d96f56658172deaa3079",
},
TestCase {
time: 3,
memory: 1024,
threads: 6,
hash: "1640b932f4b60e272f5d2207b9a9c626ffa1bd88d2349016",
},
];
let password = b"password";
let salt = b"somesalt";
for v in tests {
let want = hex::decode(v.hash).unwrap();
let have: [u8; 24] = key(password, salt, v.time, v.memory, v.threads);
assert_eq!(have.as_slice(), want.as_slice());
let have = key_with_len(password, salt, v.time, v.memory, v.threads, 24);
assert_eq!(have.as_slice(), want.as_slice());
}
}
}