use std::fmt::Write as _;
use ::hmac::{Hmac, Mac};
use sha2::Sha256;
use crate::error::Error;
type HmacSha256 = Hmac<Sha256>;
pub fn compute_hmac(data: &[u8], master_key: &[u8; 32]) -> Result<String, Error> {
let hmac_key = crate::keychain::derive_hmac_key(master_key)?;
let mut mac = HmacSha256::new_from_slice(&hmac_key)
.map_err(|e| Error::CryptoFailure(format!("HMAC init failed (unexpected): {e}")))?;
mac.update(data);
let bytes = mac.finalize().into_bytes();
let mut hex = String::with_capacity(bytes.len() * 2);
for b in &bytes {
let _ = write!(hex, "{b:02x}");
}
Ok(hex)
}
#[must_use]
pub fn split_hmac(content: &str) -> (&str, Option<String>) {
for line in content.lines().rev() {
let trimmed = line.trim();
if trimmed.starts_with("# hmac = \"") && trimmed.ends_with('"') {
let hmac_hex = &trimmed["# hmac = \"".len()..trimmed.len() - 1];
if let Some(pos) = content.rfind(line) {
let toml_part = content[..pos].trim_end();
return (toml_part, Some(hmac_hex.to_string()));
}
}
}
(content, None)
}