use core::{marker::PhantomData, ops::Sub};
use aead::{
Key,
array::{Array, ArraySize},
consts::U32,
};
use digest::OutputSizeUser;
#[cfg(feature = "zeroize")]
use zeroize::Zeroize;
use super::message_key::MessageKey;
use crate::{
FloeAead, FloeKdf,
types::{FloeIv, HeaderTag},
utils::floe_kdf,
};
pub(crate) struct FloeKey<'a, A, K>
where
A: FloeAead,
K: FloeKdf,
{
key: &'a Key<A>,
_phantom_aead: PhantomData<A>,
_phantom: PhantomData<K>,
}
impl<'a, A, K> FloeKey<'a, A, K>
where
A: FloeAead,
K: FloeKdf,
{
pub(crate) fn new(key: &'a Key<A>) -> Self {
Self { key, _phantom_aead: PhantomData, _phantom: PhantomData }
}
pub(crate) fn derive_header_tag<const N: usize, const S: u32>(
&self,
floe_iv: &FloeIv<N>,
associated_data: &[u8],
) -> HeaderTag
where
<K as OutputSizeUser>::OutputSize: Sub<U32>,
<<K as OutputSizeUser>::OutputSize as Sub<U32>>::Output: ArraySize,
{
const PURPOSE: &[u8] = b"HEADER_TAG:";
let output = floe_kdf::<A, K, N, S>(self.key, floe_iv, associated_data, PURPOSE);
let (inner, mut _rest) = Array::split::<U32>(output.into_bytes());
#[cfg(feature = "zeroize")]
_rest.zeroize();
HeaderTag { inner }
}
pub(crate) fn derive_message_key<const N: usize, const S: u32>(
&self,
floe_iv: &FloeIv<N>,
associated_data: &[u8],
) -> MessageKey<A, K>
where
<K as OutputSizeUser>::OutputSize: Sub<<K as FloeKdf>::KeySize>,
<<K as OutputSizeUser>::OutputSize as Sub<<K as FloeKdf>::KeySize>>::Output: ArraySize,
{
const PURPOSE: &[u8] = b"MESSAGE_KEY:";
let output = floe_kdf::<A, K, N, S>(self.key, floe_iv, associated_data, PURPOSE);
let (key, mut _rest) = Array::split::<<K as FloeKdf>::KeySize>(output.into_bytes());
#[cfg(feature = "zeroize")]
_rest.zeroize();
MessageKey { key, _phantom_aead: PhantomData, _phantom: PhantomData }
}
}