#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use zeroize::Zeroize;
use crate::classic::crypto_kdf::crypto_kdf_derive_from_key;
use crate::constants::{CRYPTO_KDF_CONTEXTBYTES, CRYPTO_KDF_KEYBYTES};
use crate::error::Error;
use crate::types::*;
pub type Key = StackByteArray<CRYPTO_KDF_KEYBYTES>;
pub type Context = StackByteArray<CRYPTO_KDF_CONTEXTBYTES>;
#[cfg_attr(
feature = "serde",
derive(Zeroize, Clone, Debug, Serialize, Deserialize)
)]
#[cfg_attr(not(feature = "serde"), derive(Zeroize, Clone, Debug))]
pub struct Kdf<Key: ByteArray<CRYPTO_KDF_KEYBYTES>, Context: ByteArray<CRYPTO_KDF_CONTEXTBYTES>> {
main_key: Key,
context: Context,
}
pub type StackKdf = Kdf<Key, Context>;
#[cfg(any(feature = "nightly", all(doc, not(doctest))))]
#[cfg_attr(all(feature = "nightly", doc), doc(cfg(feature = "nightly")))]
pub mod protected {
use super::*;
pub use crate::protected::*;
pub use crate::types::*;
pub type Key = HeapByteArray<CRYPTO_KDF_KEYBYTES>;
pub type Context = HeapByteArray<CRYPTO_KDF_CONTEXTBYTES>;
pub type LockedKdf = Kdf<Locked<Key>, Locked<Context>>;
}
impl<Key: NewByteArray<CRYPTO_KDF_KEYBYTES>, Context: NewByteArray<CRYPTO_KDF_CONTEXTBYTES>>
Kdf<Key, Context>
{
pub fn gen() -> Self {
Self {
main_key: Key::gen(),
context: Context::gen(),
}
}
}
impl<Key: ByteArray<CRYPTO_KDF_KEYBYTES>, Context: ByteArray<CRYPTO_KDF_CONTEXTBYTES>>
Kdf<Key, Context>
{
pub fn derive_subkey<Subkey: NewByteArray<CRYPTO_KDF_KEYBYTES>>(
&self,
subkey_id: u64,
) -> Result<Subkey, Error> {
let mut subkey = Subkey::new_byte_array();
crypto_kdf_derive_from_key(
subkey.as_mut_array(),
subkey_id,
self.context.as_array(),
self.main_key.as_array(),
)?;
Ok(subkey)
}
pub fn derive_subkey_to_vec(&self, subkey_id: u64) -> Result<Vec<u8>, Error> {
self.derive_subkey(subkey_id)
}
pub fn from_parts(main_key: Key, context: Context) -> Self {
Self { main_key, context }
}
pub fn into_parts(self) -> (Key, Context) {
(self.main_key, self.context)
}
}
impl Kdf<Key, Context> {
pub fn gen_with_defaults() -> Self {
Self {
main_key: Key::gen(),
context: Context::gen(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_kdf() {
let key = StackKdf::gen();
let _subkey = key.derive_subkey_to_vec(0).expect("derive failed");
}
}