Keys & encryption
Key inventory
Section titled “Key inventory”| Key | Protects | Lives | Rotation |
|---|---|---|---|
Vault master key (VAULT_MASTER_KEY, 32-byte AES) | Every artifact’s data key — effectively the whole vault | Deployment secret store (Railway variable in the reference deployment); ideally KMS or hardware token | Re-wrap procedure below |
| Per-artifact data keys (AES-256-GCM) | One artifact each | Only in wrapped form, in the database | Never rotated — destroyed on erasure |
| Attestation signing key (Ed25519) | Authenticity of attestations | PEM on the persistent volume (ATTESTATION_PRIVATE_KEY_PATH) | Generate new; dual-publish public keys during transition |
Webhook signing key (WEBHOOK_SIGNING_KEY) | Webhook authenticity | Deployment secret store; shared with consumers out-of-band | Issue new, run dual-verify window on consumers, retire old |
API keys (BAQSHI_API_KEYS) | The whole backend API | Deployment secret store (comma-separated list) | Append new key → migrate callers → remove old (zero downtime) |
| Handoff tokens | One capture flow each | Database rows | Self-expire in 30 min; revocable per row |
The one rule that matters most
Section titled “The one rule that matters most”Back up the vault master key somewhere the deployment platform is not. A password manager entry or a sealed offline note. This is deliberate: losing it destroys the vault (that’s what makes erasure trustworthy) — so treat it with the same care as the data itself. Never commit it; never log it.
Master key rotation (re-wrap)
Section titled “Master key rotation (re-wrap)”Blobs never need re-encrypting — only the small wrapped keys do:
- Generate a new 32-byte key; keep both old and new available.
- For each artifact row: unwrap the data key with the old master, re-wrap with the new, update the row (a short script inside a transaction; the vault blobs are untouched).
- Swap
VAULT_MASTER_KEYto the new value, restart, verify a random sample of artifacts decrypts. - Destroy the old key.
Rotate on: personnel change with key access, any suspicion of exposure, or a calendar cadence you set (annual is a sane default).
Encryption details (for auditors)
Section titled “Encryption details (for auditors)”- Cipher: AES-256-GCM, 12-byte random nonce per operation, nonce prepended to ciphertext.
- AAD: artifact encryption binds the verification ID; key-wrapping binds a fixed context string — cross-record replay fails authentication.
- Hashing: SHA-256 for artifact integrity (plaintext hash stored), audit chaining, and API-key fingerprints.
- Signatures: Ed25519 (attestations), HMAC-SHA256 (webhooks).
- Randomness: all keys/nonces/tokens from the OS CSPRNG.
- Dev fallback: without a configured master key, a local one is generated and
file-persisted (0600) so development works — production must always set
VAULT_MASTER_KEYexplicitly.