use scrypt::scrypt as scrypt_hash;
pub fn scrypt(
pass: impl AsRef<[u8]>,
salt: impl AsRef<[u8]>,
output_len: usize,
) -> Vec<u8> {
let params = scrypt::Params::recommended();
let mut output = vec![0u8; output_len];
scrypt_hash(pass.as_ref(), salt.as_ref(), ¶ms, &mut output)
.expect("scrypt failed");
output
}
pub fn scrypt_opt(
pass: impl AsRef<[u8]>,
salt: impl AsRef<[u8]>,
output_len: usize,
log_n: u8, r: u32, p: u32, ) -> Vec<u8> {
let params = scrypt::Params::new(log_n, r, p, output_len)
.expect("Invalid Scrypt parameters");
let mut output = vec![0u8; output_len];
scrypt_hash(pass.as_ref(), salt.as_ref(), ¶ms, &mut output)
.expect("scrypt failed");
output
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_scrypt_basic() {
let pass = b"password";
let salt = b"salt";
let output = scrypt(pass, salt, 32);
assert_eq!(output.len(), 32);
let output2 = scrypt(pass, salt, 32);
assert_eq!(output, output2);
}
#[test]
fn test_scrypt_different_salt() {
let pass = b"password";
let salt1 = b"salt1";
let salt2 = b"salt2";
let out1 = scrypt(pass, salt1, 32);
let out2 = scrypt(pass, salt2, 32);
assert_ne!(out1, out2);
}
#[test]
fn test_scrypt_opt_basic() {
let pass = b"password";
let salt = b"salt";
let output = scrypt_opt(pass, salt, 32, 15, 8, 1);
assert_eq!(output.len(), 32);
}
#[test]
fn test_scrypt_output_length() {
let pass = b"password";
let salt = b"salt";
for len in [16, 24, 32, 64] {
let output = scrypt(pass, salt, len);
assert_eq!(output.len(), len);
}
}
}