Key Rotation Procedure

How to rotate signing keys, API keys, and other cryptographic material

Public

Key Rotation Procedure

Implements: Cryptography Policy Section 4 (Key Management) Owner: Cryptography Specialist Last Updated: 19 June 2026 Next Review: 21 November 2026


Maelstrom AI runs two in-scope platforms under one ISMS: Provii (privacy-preserving age verification) and downpipes (no-custody backup and disaster recovery for the Cloudflare data layer). This runbook covers rotation of the cryptographic material Maelstrom manages across both: Provii signing keys, HMAC secrets and tokens, and the two downpipes vendor-side signers (Licence Signer, Update Signer).

The keys that protect downpipes backup contents — break-glass, operational and archive-signer keys — are customer-held and no-custody: they are customer-generated, held offline by the customer, and never reach Maelstrom. Maelstrom cannot decrypt, recover or rotate them. Safeguarding and rotating those keys is a complementary user-entity control (CUEC) borne by the customer; see downpipes Customer-Held Keys for the boundary. The companion Key Rotation Plan records the target cadence and implementation status for every key the ISMS tracks.


Key Inventory

Key TypeLocationRotation ScheduleImpact of Rotation
Issuer signing key (RedJubjub)Cloudflare Workers Secret (provii-issuer)Annual or on compromiseAll existing credentials invalidated, users must re-issue
Verifier HMAC keysCloudflare Workers Secret (provii-verifier)90 days (recommended)Existing HMAC signatures become invalid; verifiers must update
API keys (customer)Cloudflare KV (provii-management)Customer-managed; 90-day recommendationOld key stops working; customer updates integration
JWKS public keysCloudflare KV (public endpoint)Updated when signing key rotatesVerifiers fetch new keys from JWKS endpoint
Cloudflare API tokenCloudflare DashboardAnnualCI/CD must be updated with new token
GitHub Actions secretsGitHub Settings > SecretsWhen Cloudflare token rotatesCI workflows use new token
DOCS_SESSION_HMAC_KEY (docs interactive sandbox session cookie HMAC)Cloudflare Secrets Store (internal binding; ID maintained internally)Planned 90 days. The rotation runbook and the kid-header flow are planned work. Current deployment is single-kid per the docs session layer at demo-web-provii-agegate/src/docs/session.ts.Until the dual-kid flow lands, rotation invalidates all active docs-session bearers in flight. The planned kid prefix on the bearer and dual-key acceptance will let rotation proceed without invalidating in-flight sessions. Rotation runbook entry is tracked at operations/key-rotation-plan.md.
downpipes Licence Signer (mints licence tokens)Cloudflare Secrets Store (control-plane)Annual or on compromiseControl-plane is fail-open: it never gates backup or restore, so rotation cannot interrupt a customer’s data path. New tokens are minted under the new key; existing tokens honour their stated validity.
downpipes Update Signer (signs update-channel artefacts)Held offline by the operator; never deployed to any WorkerAnnual or on compromiseEngine verifies signatures against a pinned public key before applying a pulled update. Rotating the signer requires re-pinning the new public key in the engine ahead of the first artefact signed under it.
downpipes customer-held keys (break-glass, operational, archive-signer)Customer’s own offline storage (encrypted USB, password manager, or Shamir split)Customer-managedNo-custody — Maelstrom cannot rotate these. Customer re-runs the in-browser key ceremony and re-seals/re-fans archives. See downpipes Customer-Held Keys.

Issuer Signing Key Rotation

This is the most impactful rotation. All existing user credentials become invalid.

Pre-Rotation

  1. Communicate: Notify all known issuers and verifiers at least 30 days in advance
  2. Plan downtime window: Coordinate with customers for minimal impact

Rotation

  1. Generate new RedJubjub keypair
  2. Update the provii-issuer secret:
    wrangler secret put SIGNING_KEY --env production
  3. Update the JWKS endpoint with the new public key (add new key, keep old key for a transition period)
  4. Deploy provii-issuer

Post-Rotation

  1. Monitor for errors (users with old credentials will fail verification)
  2. After transition period (e.g., 7 days), remove old public key from JWKS
  3. Document rotation in change log

Customer API Key Rotation

  1. Customer requests new key via Admin Portal or contacts support
  2. Generate new API key in provii-management
  3. Provide new key to customer via secure channel
  4. Customer updates their integration
  5. Customer confirms new key works
  6. Revoke old key

Cloudflare API Token Rotation

  1. Generate new token in Cloudflare Dashboard with same permissions
  2. Update GitHub Actions secrets in all repositories that use the token:
    gh secret set CLOUDFLARE_API_TOKEN --body "new-token-value" --repo provii/REPO_NAME
  3. Verify CI/CD works by triggering a test deployment
  4. Revoke old token in Cloudflare Dashboard

downpipes Licence Signer Rotation

The Licence Signer lives in the control-plane’s Cloudflare Secrets Store and mints downpipes licence tokens. The control-plane is fail-open — it never gates backup or restore — so rotating this signer cannot interrupt any customer’s data path.

  1. Generate a new Licence Signer keypair
  2. Update the control-plane secret:
    wrangler secret put DOWNPIPES_LICENCE_SIGNER --env control-plane
  3. Publish the new public key alongside the previous one so tokens minted under either generation continue to validate through the transition period
  4. Mint fresh tokens under the new key; allow existing tokens to honour their stated validity
  5. After the transition period, retire the old public key
  6. Document rotation in the change log and the Key Rotation Log

downpipes Update Signer Rotation

The Update Signer is held offline by the operator and is never deployed to any Worker. The engine verifies update-channel artefacts against a pinned public key before applying a pulled update (updates are pulled, never pushed; canary-gated with automatic rollback).

Re-pin the new public key in the engine **before** any artefact is signed under the new Update Signer. Pulling an artefact signed by an unpinned key will fail signature verification and the update will not apply.
  1. Generate a new Update Signer keypair offline
  2. Stage the new pinned public key in the engine’s verification set, retaining the current pinned key
  3. Ship a signature-pinned update that carries the new pinned public key; let it roll out under the existing key
  4. Once the new pin is confirmed in the field, begin signing artefacts with the new Update Signer
  5. After the transition, remove the retired pinned public key in a subsequent signed update
  6. Keep the offline Update Signer in its offline custody throughout; document rotation in the change log and the Key Rotation Log

downpipes Customer-Held Keys (No-Custody)

downpipes seals customer backups under customer-held keys, in the customer’s own Cloudflare account, under the customer’s own keys. The key set — break-glass, operational and archive-signer — is customer-generated via a guided in-browser key ceremony, with a printed recovery sheet and offline-storage guidance (encrypted USB, password manager, or Shamir split; default two-recipient posture, strict break-glass-only opt-out).

Because downpipes is **no-custody**, these keys never reach Maelstrom. **Maelstrom cannot decrypt, recover or rotate them.** Rotating, re-issuing or recovering the customer-held key set is a complementary user-entity control (CUEC) borne by the customer.

Customer-side rotation, performed by the customer in their own account:

  1. Re-run the in-browser key ceremony to generate the replacement key(s); produce and store the new recovery sheet offline
  2. Re-seal future archives under the new key; previously sealed archives remain readable only with the key generation under which they were sealed, so retain prior keys for as long as their archives are within retention
  3. Confirm the 3-2-1 fan-out continues to land sealed archives at the two or more customer-controlled destinations
  4. Verify a restore (including the offline downpipe reader path, which restores from archive bytes plus the customer’s offline key alone) before retiring superseded keys

Dogfooding. Maelstrom’s entire Cloudflare estate is backed up by our own production instance of downpipes. In that deployment Maelstrom holds the operator keys (break-glass, operational, archive-signer), created through the same in-browser ceremony and stored offline, and follows the customer-side rotation above. See Cloudflare Backup Evidence.


Emergency Key Rotation (Compromise)

If a key is suspected compromised:

  1. Rotate immediately. Do not wait for a maintenance window
  2. Revoke the old key
  3. Assess impact: What could an attacker do with the compromised key?
  4. Notify affected parties per incident response playbook
  5. Review logs for any unauthorised use of the compromised key
  6. Document as a P1/P2 incident