use crypto_core::CryptoError;
use pbkdf2::pbkdf2_hmac;
use sha2::{Sha256, Sha512};
use zeroize::Zeroizing;
use crate::types::{
validate_output_len, Pbkdf2Iterations, Pbkdf2Output, Pbkdf2Password, Pbkdf2Prf, Pbkdf2Salt,
};
pub struct Pbkdf2Request<'a> {
pub prf: Pbkdf2Prf,
pub password: &'a Pbkdf2Password,
pub salt: &'a Pbkdf2Salt,
pub iterations: Pbkdf2Iterations,
pub output_len: usize,
}
pub fn derive_key(request: &Pbkdf2Request<'_>) -> Result<Pbkdf2Output, CryptoError> {
validate_output_len(request.output_len, request.prf)?;
let mut output = Zeroizing::new(vec![0u8; request.output_len]);
match request.prf {
Pbkdf2Prf::HmacSha256 => pbkdf2_hmac::<Sha256>(
request.password.as_bytes(),
request.salt.as_bytes(),
request.iterations.as_u32(),
&mut output,
),
Pbkdf2Prf::HmacSha512 => pbkdf2_hmac::<Sha512>(
request.password.as_bytes(),
request.salt.as_bytes(),
request.iterations.as_u32(),
&mut output,
),
}
Ok(Pbkdf2Output::from_zeroizing(output))
}