RFC-010: Autonomous Intelligence Governance Protocol (AIGP) — 4. HMAC Authentication
AIGP Specification › RFC-010: Autonomous Intelligence Governance Protocol (AIGP) › 4. HMAC Authentication
← 3. Protocol Messages · Section index · 5. Governance Modes →
4. HMAC Authentication
All protocol messages MUST be authenticated using HMAC-SHA256.
4.1 Signature Computation
import hashlibimport hmacfrom datetime import datetime, timezone
def compute_hmac(secret: str, timestamp: str, method: str, path: str, body_bytes: bytes) -> str: """Compute HMAC-SHA256 signature for an AIGP request.""" body_hash = hashlib.sha256(body_bytes).hexdigest() message = f"{timestamp}\n{method}\n{path}\n{body_hash}" return hmac.new(secret.encode(), message.encode(), hashlib.sha256).hexdigest()4.2 Validation
HMAC_MAX_AGE_SECONDS = 300 # 5-minute replay window
async def validate_hmac(request, db) -> str: """Validate HMAC signature. Returns app_id if valid.""" sig_header = request.headers.get("X-AIGP-Signature", "") timestamp = request.headers.get("X-AIGP-Timestamp", "") app_id = request.headers.get("X-AIGP-App-Id", "")
# Replay protection ts = datetime.fromisoformat(timestamp) age = (datetime.now(timezone.utc) - ts).total_seconds() if abs(age) > HMAC_MAX_AGE_SECONDS: raise ValueError("Timestamp too old")
# Load app's HMAC secret reg = await db.get_registration(app_id) secret = reg.get("hmac_secret", "")
# Compute expected signature body = await request.body() expected = compute_hmac(secret, timestamp, request.method, request.url.path, body)
# Compare provided = sig_header.replace("hmac-sha256=", "") if not hmac.compare_digest(expected, provided): raise ValueError("Invalid HMAC signature")
return app_id← 3. Protocol Messages · Section index · 5. Governance Modes →