use std::convert::TryFrom;
use zeroize::Zeroizing;
use crate::key::{secret_key_from_raw, SecretKey};
use crate::{Argon2Parameters, Error, Header, KeyDerivationVersion, Result};
use super::{DerivationParameters, DerivationParametersPayload};
#[derive(Clone)]
pub struct KeyDerivationV2 {
pub params: Argon2Parameters,
}
impl core::fmt::Debug for KeyDerivationV2 {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "KeyDerivationV2")
}
}
impl KeyDerivationV2 {
pub fn derive(&self, key: &[u8]) -> Result<Zeroizing<Vec<u8>>> {
Ok(Zeroizing::new(self.params.compute(key)?))
}
}
impl From<&KeyDerivationV2> for Vec<u8> {
fn from(v2: &KeyDerivationV2) -> Self {
Vec::from(&v2.params)
}
}
impl TryFrom<&[u8]> for KeyDerivationV2 {
type Error = Error;
fn try_from(data: &[u8]) -> Result<Self> {
Ok(KeyDerivationV2 {
params: Argon2Parameters::try_from(data)?,
})
}
}
pub struct Argon2 {
params: Argon2Parameters,
}
impl Argon2 {
pub fn new() -> Self {
Self {
params: Argon2Parameters::default(),
}
}
pub fn with_params(params: Argon2Parameters) -> Self {
Self { params }
}
pub fn parameters(self) -> DerivationParameters {
let v2 = KeyDerivationV2 {
params: self.params,
};
let mut header: Header<DerivationParameters> = Header::default();
header.version = KeyDerivationVersion::V2;
DerivationParameters {
header,
payload: DerivationParametersPayload::V2(v2),
}
}
pub fn derive(&self, key: &[u8]) -> Result<(SecretKey, DerivationParameters)> {
let v2 = KeyDerivationV2 {
params: self.params.clone(),
};
let raw = v2.derive(key)?;
let secret_key = secret_key_from_raw(raw)?;
let mut header: Header<DerivationParameters> = Header::default();
header.version = KeyDerivationVersion::V2;
let derivation_params = DerivationParameters {
header,
payload: DerivationParametersPayload::V2(v2),
};
Ok((secret_key, derivation_params))
}
}
impl Default for Argon2 {
fn default() -> Self {
Self::new()
}
}