1use serde::{Deserialize, Serialize};
2#[cfg(feature = "native_crypto")]
3use subtle::ConstantTimeEq;
4use zbus::zvariant::Type;
5use zeroize::{Zeroize, ZeroizeOnDrop};
6
7#[derive(Deserialize, Serialize, Type, Clone, Zeroize, ZeroizeOnDrop)]
11pub struct Mac(#[serde(with = "serde_bytes")] Vec<u8>);
12
13impl std::fmt::Debug for Mac {
14 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15 write!(f, "Mac([REDACTED])")
16 }
17}
18
19impl Mac {
20 pub(crate) const fn new(inner: Vec<u8>) -> Self {
21 Self(inner)
22 }
23
24 fn verify_slice(&self, other: &[u8]) -> bool {
26 #[cfg(feature = "native_crypto")]
27 {
28 self.0.ct_eq(other).into()
29 }
30 #[cfg(feature = "openssl_crypto")]
31 {
32 openssl::memcmp::eq(&self.0, other)
33 }
34 }
35
36 pub(crate) fn as_slice(&self) -> &[u8] {
38 self.0.as_slice()
39 }
40}
41
42impl PartialEq for Mac {
43 fn eq(&self, other: &Self) -> bool {
44 self.verify_slice(&other.0)
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 #[test]
53 fn mac_debug_is_redacted() {
54 let mac = Mac::new(vec![1, 2, 3, 4]);
55 assert_eq!(format!("{:?}", mac), "Mac([REDACTED])");
56 }
57}