use hkdf::Hkdf;
use sha2::Sha256;
use zeroize::Zeroize;
use crate::errors::{EnvVaultError, Result};
const KEY_LEN: usize = 32;
pub fn derive_secret_key(master_key: &[u8], secret_name: &str) -> Result<[u8; KEY_LEN]> {
let info = format!("envvault-secret:{secret_name}");
hkdf_derive(master_key, info.as_bytes())
}
pub fn derive_hmac_key(master_key: &[u8]) -> Result<[u8; KEY_LEN]> {
hkdf_derive(master_key, b"envvault-hmac-key")
}
fn hkdf_derive(ikm: &[u8], info: &[u8]) -> Result<[u8; KEY_LEN]> {
let hk = Hkdf::<Sha256>::new(None, ikm);
let mut okm = [0u8; KEY_LEN];
hk.expand(info, &mut okm)
.map_err(|e| EnvVaultError::KeyDerivationFailed(format!("HKDF expand failed: {e}")))?;
Ok(okm)
}
#[derive(Zeroize)]
#[zeroize(drop)]
pub struct MasterKey {
bytes: [u8; KEY_LEN],
}
impl MasterKey {
pub fn new(bytes: [u8; KEY_LEN]) -> Self {
Self { bytes }
}
pub fn as_bytes(&self) -> &[u8; KEY_LEN] {
&self.bytes
}
pub fn derive_secret_key(&self, secret_name: &str) -> Result<[u8; KEY_LEN]> {
derive_secret_key(&self.bytes, secret_name)
}
pub fn derive_hmac_key(&self) -> Result<[u8; KEY_LEN]> {
derive_hmac_key(&self.bytes)
}
}