use std::convert::TryInto;
use openmls_traits::{crypto::OpenMlsCrypto, types::CryptoError};
use serde::{Deserialize, Serialize};
use tls_codec::{TlsDeserialize, TlsSerialize, TlsSize};
use super::Ciphersuite;
const LABEL: &[u8; 11] = b"MLS 1.0 ref";
const VALUE_LEN: usize = 16;
type Value = [u8; VALUE_LEN];
#[derive(
Clone,
Copy,
Hash,
PartialEq,
Eq,
Serialize,
Deserialize,
TlsDeserialize,
TlsSerialize,
TlsSize,
PartialOrd,
Ord,
)]
pub struct HashReference {
value: Value,
}
pub type KeyPackageRef = HashReference;
pub type ProposalRef = HashReference;
impl HashReference {
pub fn new(
value: &[u8],
ciphersuite: Ciphersuite,
backend: &impl OpenMlsCrypto,
) -> Result<Self, CryptoError> {
let okm = backend.hkdf_expand(
ciphersuite.hash_algorithm(),
&backend.hkdf_extract(ciphersuite.hash_algorithm(), &[], value)?,
LABEL,
VALUE_LEN,
)?;
let value: Value = okm.try_into().map_err(|_| CryptoError::InvalidLength)?;
Ok(Self { value })
}
pub fn value(&self) -> &[u8; 16] {
&self.value
}
pub fn as_slice(&self) -> &[u8] {
&self.value
}
#[cfg(any(feature = "test-utils", test))]
pub fn from_slice(slice: &[u8]) -> Self {
let mut value = [0u8; VALUE_LEN];
value.clone_from_slice(slice);
Self { value }
}
}
impl core::fmt::Display for HashReference {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "HashReference: ")?;
for b in self.value {
write!(f, "{:02X}", b)?;
}
Ok(())
}
}
impl core::fmt::Debug for HashReference {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self)
}
}