How we encrypt your customers' keys
If you take custody of crypto for someone else, the question that matters most is: where is the master mnemonic, and who can read it?
SwyDex uses envelope encryption. Each tenant gets a Data Encryption Key (DEK) — 32 random bytes generated locally on a developer's laptop the first time we set up a region. The DEK encrypts every wallet mnemonic with AES-256-GCM. The DEK itself is then wrapped by a Key Encryption Key (KEK) held in Google Cloud KMS. We never write the plaintext DEK to disk; the wrapped blob lives in our env file.
At container start, the runtime calls kms.decrypt exactly once. The plaintext DEK lives in process memory only. The runtime service account has Decrypt-only KMS permissions — it cannot mint new wrapped blobs. To rotate, an operator authenticates as a separate user identity with Owner permissions on the project.
What this protects against:
- Someone with read access to our database walking off with an encrypted mnemonic. Without the DEK they have ciphertext only.
- Someone with read access to our app filesystem getting the wrapped blob. Without the KMS service account, they can't unwrap.
- Someone hijacking the running app process. They can decrypt existing wallets — but they can't enroll new ones under a different DEK and pretend it's us.
What it does not protect against: an attacker who compromises the operator's laptop while they're holding the plaintext DEK during initial setup. We address that with hardware-token auth on KMS access and a short window for the setup ritual. Past initial setup, the plaintext DEK is always wrapped on disk.
If we ever lose KMS access, we lose the ability to decrypt. That is by design. The wrapped blob in our env files is useless without us, and the KMS key is useless to us if we don't have a mechanism to bring it back.