Skip to content

RFC-010: Autonomous Intelligence Governance Protocol (AIGP) — 4. HMAC Authentication

AIGP SpecificationRFC-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 hashlib
import hmac
from 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 →