Skip to content

[FEATURE][SECURITY]: Cryptographic request and response signing #230

@crivetimihai

Description

@crivetimihai

🧭 Epic

Title: End-to-End JWS/HMAC Signing for Requests & Responses
Goal: Require every inbound request (and optionally every outbound response) to carry a verifiable signature; reject anything unsigned or tampered.
Why now: Spoofed calls & replay attacks are a real threat-signatures provide provenance, integrity, and non-repudiation.


🧭 Type of Feature

  • Security hardening
  • New functionality (experimental)

🙋‍♂️ User Story 1 - Verify Incoming Signatures

As a: Gateway
I want: to verify JWS signatures using server-side public keys
So that: only authentic, unmodified requests are processed.

✅ Acceptance Criteria

Scenario: Reject invalid JWS
Given gateway has keyset K
And receives POST /rpc signed with unknown key
Then respond 401 "signature_unknown"
And MUST NOT dispatch the RPC

🙋‍♂️ User Story 2 - Sign Outbound Responses

As a: API consumer
I want: every response body JWS-signed by the gateway's private key
So that: clients can assert the response is genuine and untampered in transit.

✅ Acceptance Criteria

Scenario: Validate response signature
Given client holds gateway's public key
When it receives JSON-RPC result with `X-Signature`
Then cryptographic verification MUST succeed

🙋‍♂️ User Story 3 - Replay-Attack Defense

As a: Security engineer
I want: each request to include a nonce & timestamp checked against an LRU cache
So that: attackers cannot replay a captured signed message.

✅ Acceptance Criteria

Scenario: Detect replayed nonce
Given nonce "abc123" was seen within 5 min window
When a second request arrives with same nonce
Then respond 409 "replay_detected"

📐 Design Sketch

sequenceDiagram
  participant C as Client
  participant G as Gateway
  C->>G: JWS({jsonrpc,id,method,nonce,ts})
  G->>G: Verify sig & freshness
  G-->>C: JWS({result}, headers:{X-Signature})
Loading
Component Change Detail
crypto_signature.py NEW JWS/HMAC verify & sign helpers
Middleware NEW SignatureVerifier, SignatureSigner
nonce_cache NEW In-memory + Redis backend
Config ADD TRUSTED_KEYS, SIGN_RESPONSES, NONCE_TTL

🔄 Roll-out Plan

  1. Phase 0: Generate keypair; publish gateway public key at /.well-known/jwks.json.
  2. Phase 1: Accept either signed or unsigned; log unsigned traffic.
  3. Phase 2: Require signatures for POST /rpc in staging; optional for responses.
  4. Phase 3: Enforce on all routes; enable response-signing flag; rotate keys annually.

📝 Spec-Draft Clauses

  1. Integrity - "Requests MUST carry a detached JWS (RFC 7515) over the canonical JSON body."
  2. Freshness - "Implementations MUST reject any nonce replayed within NONCE_TTL seconds."
  3. Response Signing - "Servers SHOULD sign responses; clients MAY require it."

📣 Next Steps

  • Draft JWS canonicalization rules (JSON-Canonicalization Scheme).
  • Implement nonce LRU cache prototype.
  • Write conformance tests in tests/crypto/.

Metadata

Metadata

Assignees

Labels

MUSTP1: Non-negotiable, critical requirements without which the product is non-functional or unsafeenhancementNew feature or requestpythonPython / backend development (FastAPI)readyValidated, ready-to-work-on itemssecurityImproves security

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions