> ## Documentation Index
> Fetch the complete documentation index at: https://docs.knoxcall.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Encryption threat model

> What KnoxCall's portable encryption defends against, the trust boundaries, and — honestly — what it does not protect against. Published so your reviewers can reason about residual risk.

# Encryption threat model

This page states plainly what the [`kc:` encryption](/essentials/encryption/ciphertext-spec), [vaults](/essentials/vaults/overview), and [capability tokens](/essentials/encryption/overview#client-side-reveal-without-an-api-key) 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, vault `wrapped_value` blobs) — useless without the key.
* **Wrapped keys** — app private keys and tenant master keys, each wrapped under the layer above (see the [key hierarchy](/essentials/encryption/ciphertext-spec#key-hierarchy--custody)).

In **dual-custody** vaults, KnoxCall holds **no value at all** — you keep the ciphertext.

## 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_B64` and 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](/security/client-permissions), API-key scopes, and capability tokens.
* **Plaintext you send us in the clear.** The `/v1/encrypt` request 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 only `kc:` 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](/monitoring/audit-logs).

## Verify it yourself

The cryptographic construction is published in full in the [ciphertext spec](/essentials/encryption/ciphertext-spec). The `kc:` 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).
