Key rotation policy
This page documents the key management and rotation policy for all cryptographic material CloakAPI controls. For keys controlled by the customer (e.g. their own LLM provider API keys stored via BYOK), see the Gateway authentication page.
Receipt signing keys
Receipt signing keys are used to produce the ECDSA signatures on receipt envelopes. They are the most security-critical keys in the system.
| Property | Value |
|---|---|
| Algorithm | ECDSA P-256 (secp256r1) |
Key ID (kid) format | gw-{region}-{YYYY}-q{quarter} — example: gw-prod-2026-q2 |
| Rotation period | Quarterly target. Gateway-wide key rotation is a manual operation; a scheduled quarterly job raises the reminder |
| Overlap window | A pending next key can be published in the JWKS before it becomes the active signing key |
| Retention for verification | A rotated-out gateway key stays in the JWKS for as long as it is listed in the gateway’s retired-key configuration, which is maintained by hand; nothing in the code removes it on a timer |
| Post-rotation status | Old kid entries are marked x-cloakapi-active: false in the JWKS — they no longer sign new receipts but remain usable for historical verification. The JWKS has no revoked field; a compromised key would be withdrawn by taking it out of the published set. |
JWKS endpoint
https://api.cloakapi.io/api/.well-known/cloakapi-receipt-pubkeys.jwksThis endpoint returns a standard JWK Set. Each entry includes:
kid— key identifier. The current gateway key usesgw-{region}-{YYYY}-q{quarter}(gw-prod-2026-q2); older and per-tenant keys in the set use other forms (for examplegw-eu-west-4a3cfb59, or a 64-hex fingerprint)kty—"EC"crv—"P-256"x,y— public key coordinates (base64url)use—"sig"x-cloakapi-active—trueon the current signing key,falseon keys that have been rotated out (which still verify their historical receipts)alg—"ES256", andkey_ops—["verify"]
Example entry for an active key:
{ "kid": "gw-prod-2026-q2", "kty": "EC", "crv": "P-256", "use": "sig", "x-cloakapi-active": true, "x": "<base64url>", "y": "<base64url>"}Example entry for a rotated-out key (inactive, but still verifies historical receipts):
{ "kid": "gw-prod-2026-q1", "kty": "EC", "crv": "P-256", "use": "sig", "x-cloakapi-active": false, "x": "<base64url>", "y": "<base64url>"}Rotation schedule
Keys are named after the quarter they are activated. Rotation is manual, so a key can stay active past its quarter: gw-prod-2026-q2 was still the active signing key when the JWKS was read on 2026-09-25. The overlap window means receipts signed near a rotation may carry either kid.
Customer API keys
Customer API keys authenticate requests to the CloakAPI gateway.
| Property | Value |
|---|---|
| Rotation | User-driven — rotated on demand from the dashboard or via the management API |
| Grace period | None — rotation deactivates the old key immediately and atomically (the new key is created and the old key deactivated in the same transaction). Have the new key deployed before you rely on it. |
| Format | cloak_live_<43 url-safe base64 chars> (32 random bytes); all keys carry the cloak_ prefix |
| Storage | Keys are stored as SHA-256 hashes server-side. The plaintext is shown once at creation and not recoverable |
| Revocation | Immediate — a revoked key fails with HTTP 401 within seconds of revocation |
| Expiry | None by default. A key can be given an optional expiry date at creation; after it, requests with that key fail with HTTP 401 expired_api_key |
Rotation procedure
- In the dashboard go to API keys, and choose Rotate on the key.
- A new key is generated and displayed once — copy it immediately.
- The old key is deactivated at the moment of rotation — there is no grace window. Deploy the new key to your application right away.
- If a key is believed compromised, Revoke and Rotate are equally immediate; either invalidates the old key at once.
HSM / KMS path
Key ID reference table
kid | Status | Notes |
|---|---|---|
gw-prod-2026-q2 | Active | Current gateway signing key (read from the JWKS 2026-09-25) |
| Earlier keys | Inactive (x-cloakapi-active: false) | Available in JWKS for historical receipt verification |
This table reflects the state at documentation publish time. The JWKS endpoint is always authoritative.