use super::{ClusterKey, TAG_LEN};
pub(crate) struct Tag([u8; TAG_LEN]);
impl Tag {
pub(super) fn as_bytes(&self) -> &[u8; TAG_LEN] {
&self.0
}
}
pub(crate) trait Mac {
fn tag(key: &ClusterKey, message: &[u8]) -> Tag;
fn verify(key: &ClusterKey, message: &[u8], tag: &[u8]) -> bool;
}
#[cfg(feature = "mac-blake3")]
pub(crate) struct Blake3Mac;
#[cfg(feature = "mac-blake3")]
impl Mac for Blake3Mac {
fn tag(key: &ClusterKey, message: &[u8]) -> Tag {
Tag(*blake3::keyed_hash(key.as_bytes(), message).as_bytes())
}
fn verify(key: &ClusterKey, message: &[u8], tag: &[u8]) -> bool {
let Ok(tag) = <[u8; TAG_LEN]>::try_from(tag) else {
return false;
};
blake3::keyed_hash(key.as_bytes(), message) == blake3::Hash::from_bytes(tag)
}
}
#[cfg(all(feature = "mac-hmac", not(feature = "mac-blake3")))]
pub(crate) struct HmacSha256Mac;
#[cfg(all(feature = "mac-hmac", not(feature = "mac-blake3")))]
impl Mac for HmacSha256Mac {
fn tag(key: &ClusterKey, message: &[u8]) -> Tag {
use hmac::{Hmac, Mac as _};
let mut mac = Hmac::<sha2::Sha256>::new_from_slice(key.as_bytes())
.expect("HMAC accepts any key length");
mac.update(message);
Tag(mac.finalize().into_bytes().into())
}
fn verify(key: &ClusterKey, message: &[u8], tag: &[u8]) -> bool {
use hmac::{Hmac, Mac as _};
let mut mac = Hmac::<sha2::Sha256>::new_from_slice(key.as_bytes())
.expect("HMAC accepts any key length");
mac.update(message);
mac.verify_slice(tag).is_ok()
}
}
#[cfg(feature = "mac-blake3")]
pub(crate) type ClusterMac = Blake3Mac;
#[cfg(all(feature = "mac-hmac", not(feature = "mac-blake3")))]
pub(crate) type ClusterMac = HmacSha256Mac;