Encryption threat model
This page states plainly what thekc: encryption, vaults, and capability tokens defend against, where the trust boundaries are, and what is explicitly out of scope. Naming the residual risk is deliberate — it is how you evaluate whether the control fits your compliance posture.
Trust boundary
Plaintext exists only transiently, inside the KnoxCall control plane, during an encrypt or decrypt call. At rest, KnoxCall holds:- Ciphertext (
kc:values, vaultwrapped_valueblobs) — useless without the key. - Wrapped keys — app private keys and tenant master keys, each wrapped under the layer above (see the key hierarchy).
What it defends against
| Threat | Defence |
|---|---|
| Database-only breach | A dump yields ciphertext + wrapped keys. The master key is not in the database in KMS mode; under BYOK it is wrapped by your KMS. No plaintext is recoverable from the DB alone. |
| Cross-tenant access | tenant_id is bound into key derivation (HKDF info) and re-checked at decrypt. A ciphertext from tenant A cannot be decrypted as tenant B — the GCM tag fails. |
| Tampering / forgery | AES-256-GCM authenticates the payload, and the full kc: header is bound as additional authenticated data. Flipping any bit of the ciphertext or the header fails decryption. |
| Wrong data-role | The purpose (data-role) is folded into the KDF. A value encrypted under pci will not decrypt unless pci is presented — policy travels with the data. |
| Replay of client reveals | Capability tokens are single-use (atomically consumed), payload-pinned (bound to one exact ciphertext), and short-lived (≤10 min). A leaked token reveals at most one value, once, within minutes. |
| Sandbox/Test ↔ Live confusion | Test and Live keys, tokens, and capability tokens are distinct identities. A Test credential never satisfies a Live operation, enforced by a build-failing isolation guard. |
| Cryptographic erasure / right-to-be-forgotten | Destroying a key version permanently shreds every value under it — no need to hunt through backups. |
Residual risk (out of scope, stated honestly)
- Simultaneous compromise of the platform master key and the database (env-key mode). If an attacker obtains both
MASTER_KEY_B64and a DB dump at the same time, wrapped keys become unwrappable and plaintext is recoverable. Mitigations that raise this bar: run in KMS-unseal mode (the master key lives in AWS/GCP/Azure KMS, not on disk), adopt BYOK (the tenant master key is wrapped by your KMS, revocable by you), and — on the roadmap — run the unseal/crypto core inside a hardware enclave with remote attestation so even a KnoxCall operator cannot read plaintext. - A fully-authorised caller. Encryption does not stop a request that legitimately holds the key and the right data-role. Constrain that with client permissions, API-key scopes, and capability tokens.
- Plaintext you send us in the clear. The
/v1/encryptrequest body contains plaintext over TLS. To keep plaintext off our servers entirely, encrypt in the browser against the tenant public key (the kc: format is designed for exactly this) and send onlykc:values. - Endpoint compromise on your side. If your own server or browser is compromised at the moment it handles plaintext, that is outside KnoxCall’s boundary.
Compliance mapping
- PCI scope reduction — tokenize PANs (managed vaults) or seal them client-side (
kc:+ browser SDK) so cardholder data never lands in your downstream systems. - HIPAA / GDPR — encrypt PHI/PII at the field level; use data-roles for residency (
eu) and cryptographic erasure for deletion requests. - Audit — every encrypt, decrypt, tokenize, detokenize, and capability-token mint/consume lands in the tamper-evident audit log.
Verify it yourself
The cryptographic construction is published in full in the ciphertext spec. Thekc: format is self-describing, so you can independently parse a ciphertext, confirm the curve/IV/tag sizes, and check that the same plaintext encrypts to different ciphertexts every time (fresh ephemeral key + IV per value).