use data_encoding::BASE64URL_NOPAD;
use hmac::{Hmac, KeyInit, Mac};
use sha2::Sha256;
use topcoat::context::Cx;
const PURPOSE: &[u8] = b"tablo carried upload v1";
fn mac(cx: &Cx, field: &str, path: &str) -> Hmac<Sha256> {
let mut mac = <Hmac<Sha256> as KeyInit>::new_from_slice(&super::key::derived(cx, PURPOSE))
.expect("HMAC takes a key of any length");
for part in [field, &crate::csrf::current_token(cx), path] {
mac.update(part.as_bytes());
mac.update(b"\n");
}
mac
}
pub(crate) fn seal(cx: &Cx, field: &str, path: &str) -> String {
let tag = BASE64URL_NOPAD.encode(&mac(cx, field, path).finalize().into_bytes());
format!("{tag}.{path}")
}
pub(crate) fn open<'a>(cx: &Cx, field: &str, carried: &'a str) -> Option<&'a str> {
let (tag, path) = carried.split_once('.')?;
let tag = BASE64URL_NOPAD.decode(tag.as_bytes()).ok()?;
mac(cx, field, path).verify_slice(&tag).ok()?;
Some(path)
}