use crate::errors;
use core::num;
use ring::pbkdf2;
pub fn derive_key(
digest_algo: pbkdf2::Algorithm,
iterations: usize,
salt: &[u8],
secret: &[u8],
key: &mut [u8],
) -> Result<(), errors::Error> {
if digest_algo == pbkdf2::PBKDF2_HMAC_SHA1
|| iterations < 1
|| salt.len() == 0
{
return Err(errors::Error::CryptoParamsWeak);
}
if secret.len() == 0 || key.len() == 0 {
return Err(errors::Error::PassphraseTooSmall);
}
let iterations = num::NonZeroU32::new(iterations as u32).unwrap();
pbkdf2::derive(digest_algo, iterations, salt, secret, key);
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pbkd2_derive_key() {
let mut salt = [9; 10];
let mut secret = [99; 10];
let mut key1 = [0u8; 32];
let mut key2 = [0u8; 32];
let mut key3 = [0u8; 32];
let mut key4 = [0u8; 32];
let mut res: Result<(), errors::Error>;
let params_err = Err(errors::Error::CryptoParamsWeak);
let size_err = Err(errors::Error::PassphraseTooSmall);
res =
derive_key(pbkdf2::PBKDF2_HMAC_SHA1, 1, &salt, &secret, &mut key1);
assert_eq!(res, params_err);
res = derive_key(
pbkdf2::PBKDF2_HMAC_SHA256,
0,
&salt,
&secret,
&mut key1,
);
assert_eq!(res, params_err);
res =
derive_key(pbkdf2::PBKDF2_HMAC_SHA256, 1, &[], &secret, &mut key1);
assert_eq!(res, params_err);
res = derive_key(pbkdf2::PBKDF2_HMAC_SHA256, 1, &salt, &[], &mut key1);
assert_eq!(res, size_err);
res =
derive_key(pbkdf2::PBKDF2_HMAC_SHA256, 1, &salt, &secret, &mut []);
assert_eq!(res, size_err);
res = derive_key(
pbkdf2::PBKDF2_HMAC_SHA256,
1,
&salt,
&secret,
&mut key1,
);
assert!(res.is_ok());
salt[0] = 0;
res = derive_key(
pbkdf2::PBKDF2_HMAC_SHA256,
1,
&salt,
&secret,
&mut key2,
);
assert!(res.is_ok());
salt[0] = 9;
secret[0] = 0;
res = derive_key(
pbkdf2::PBKDF2_HMAC_SHA256,
1,
&salt,
&secret,
&mut key3,
);
assert!(res.is_ok());
secret[0] = 99;
res = derive_key(
pbkdf2::PBKDF2_HMAC_SHA256,
1,
&salt,
&secret,
&mut key4,
);
assert!(res.is_ok());
assert_ne!(key1, key2);
assert_ne!(key1, key3);
assert_ne!(key2, key3);
assert_eq!(key1, key4);
}
}