"""Pass-Window Ticket signer/verifier. Compact ticket structure intended for pre-signed pass-window triggers. Uses HMAC (blake2b) signatures for tests/POC. The ticket hash is the sha256 of the canonical serialized payload (excluding signature), which can be used as an external pointer in MFR-v2.pass_ticket_hash. """ from dataclasses import dataclass from typing import Optional import json import time import uuid import hashlib import hmac @dataclass class PassWindowTicket: window_start: int window_end: int comm_budget_bytes: int resource_budget_digest: str trigger_policy_id: str nonce: str signer: str = "" sig: str = "" @classmethod def mint(cls, window_start: int, window_end: int, comm_budget_bytes: int, resource_budget_digest: str, trigger_policy_id: str = "default", signer: str = "", key: Optional[bytes] = None) -> "PassWindowTicket": nonce = uuid.uuid4().hex[:12] t = cls(window_start=window_start, window_end=window_end, comm_budget_bytes=int(comm_budget_bytes), resource_budget_digest=resource_budget_digest, trigger_policy_id=trigger_policy_id, nonce=nonce, signer=signer, sig="") if key: t.sig = t._sign(key) return t def _canonical(self) -> str: payload = { "window_start": int(self.window_start), "window_end": int(self.window_end), "comm_budget_bytes": int(self.comm_budget_bytes), "resource_budget_digest": self.resource_budget_digest, "trigger_policy_id": self.trigger_policy_id, "nonce": self.nonce, "signer": self.signer, } return json.dumps(payload, sort_keys=True, separators=(",", ":")) def _sign(self, key: bytes) -> str: h = hmac.new(key, self._canonical().encode("utf-8"), hashlib.blake2b) return h.hexdigest()[:64] def serialize(self) -> bytes: obj = { "window_start": self.window_start, "window_end": self.window_end, "comm_budget_bytes": self.comm_budget_bytes, "resource_budget_digest": self.resource_budget_digest, "trigger_policy_id": self.trigger_policy_id, "nonce": self.nonce, "signer": self.signer, "sig": self.sig, } return json.dumps(obj, sort_keys=True, separators=(",", ":")).encode("utf-8") def ticket_hash(self) -> str: # external pointer: sha256 of canonical payload (no sig) return hashlib.sha256(self._canonical().encode("utf-8")).hexdigest() def verify(self, key: bytes) -> bool: if not self.sig: return False expected = self._sign(key) return hmac.compare_digest(expected, self.sig) @classmethod def deserialize(cls, b: bytes) -> "PassWindowTicket": obj = json.loads(b.decode("utf-8")) return cls(window_start=int(obj.get("window_start", 0)), window_end=int(obj.get("window_end", 0)), comm_budget_bytes=int(obj.get("comm_budget_bytes", 0)), resource_budget_digest=obj.get("resource_budget_digest", ""), trigger_policy_id=obj.get("trigger_policy_id", ""), nonce=obj.get("nonce", ""), signer=obj.get("signer", ""), sig=obj.get("sig", ""))