use std::iter::IntoIterator;
use ring::hmac;
#[derive(zeroize::ZeroizeOnDrop, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct DhsdSecret([u8; 32]);
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct NodeLabel([u8; 32]);
impl DhsdSecret {
pub fn from_root_secret(root_secret: [u8; 32]) -> Self {
Self::from(root_secret)
}
pub fn derive(&self, label: NodeLabel) -> Self {
let mut key = hmac::Key::new(hmac::HMAC_SHA256, &self.0);
let mut tag = hmac::sign(&key, &label.0);
let mut inner = [0u8; 32];
inner.copy_from_slice(tag.as_ref());
unsafe {
zeroize::zeroize_flat_type(&mut key);
zeroize::zeroize_flat_type(&mut tag);
}
Self(inner)
}
pub fn derive_from_iter<P: IntoIterator<Item = NodeLabel>>(&self, path: P) -> Self {
path.into_iter()
.fold(self.clone(), |a, label| a.derive(label))
}
pub fn as_array(&self) -> [u8; 32] {
self.0
}
}
impl From<[u8; 32]> for DhsdSecret {
fn from(value: [u8; 32]) -> Self {
Self(value)
}
}
impl From<[u8; 32]> for NodeLabel {
fn from(value: [u8; 32]) -> Self {
Self(value)
}
}
impl From<DhsdSecret> for [u8; 32] {
fn from(value: DhsdSecret) -> Self {
value.0
}
}
impl From<&DhsdSecret> for [u8; 32] {
fn from(value: &DhsdSecret) -> Self {
value.0
}
}
impl std::fmt::Debug for DhsdSecret {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("DhsdState").field(&"...").finish()
}
}
impl From<&str> for NodeLabel {
fn from(value: &str) -> Self {
let d = ring::digest::digest(&ring::digest::SHA256, value.as_bytes());
let mut inner = [0u8; 32];
inner.copy_from_slice(d.as_ref());
Self(inner)
}
}
impl From<String> for NodeLabel {
fn from(value: String) -> Self {
Self::from(value.as_str())
}
}
impl From<&String> for NodeLabel {
fn from(value: &String) -> Self {
Self::from(value.as_str())
}
}