Managed keys (KMS)
Secrets answer "store this value and hand it back later." A KMS key answers a different question: "encrypt, decrypt, or sign my own data with a key I never have to hold." seekrit's KMS is the same zero-knowledge machinery as the rest of the product — the key material is generated in your client and wrapped to each principal, so the server only ever stores ciphertext, public keys, and grants.
Unlike a classic server-side KMS (AWS KMS, Vault Transit), seekrit never runs the crypto for you: a client fetches its wrapped key once, unwraps it with its own private key, and then encrypts, decrypts, and signs entirely locally. The server cannot read your plaintext, and it cannot use your key.
What a key is
A managed key is org-scoped and referenced by a stable name. It has a purpose that fixes what it does:
encrypt— a symmetric AES-256-GCM key, forEncrypt/DecryptandGenerateDataKey.sign— an asymmetric ECDSA P-256 keypair. The private half is wrapped to grantees; the public half is published per version, so anyone in the org can verify a signature without holding the key.
A key may be scoped to an application or a group (or left org-wide) — the same ownership model as environments. Scope organizes keys and drives the dashboard; a grant is still what actually lets a principal use the key.
Grants: possession is access
Exactly like an environment DEK, a KMS key reaches a principal only as a
grant — the key material wrapped to that principal's public key (a wd1.
blob, ephemeral ECDH → HKDF → AES-GCM). Holding a grant row plus the matching
private key is the ability to use that key version. Admins grant and revoke;
the crypto is the hard boundary.
Envelope encryption & GenerateDataKey
Encrypt produces a versioned ce1. blob. For large payloads, GenerateDataKey
returns a fresh random data key plus that data key wrapped under the managed
key (a dk1. blob): encrypt your bulk data with the plaintext data key, store
the wrapped form beside it, and recover it later with the managed key. This is
the S3-style envelope pattern, done client-side.
Encryption context (AAD)
Encrypt takes an optional encryption context — an arbitrary string bound
into the ciphertext as additional authenticated data, mirroring AWS KMS. Decrypt
must supply the same context or it fails. Use it to pin a ciphertext to where it
belongs (tenant=acme, field=ssn), so a blob can't be silently moved to a
different record. The key id and version are always bound too, so a ce1. blob
can never be replayed under a different key or version.
Versions & rotation
Every key has a current version that new operations use. Rotating a key adds a new version — the client generates fresh material and re-wraps it for every current grantee — and bumps the current version. Old versions are retained, so ciphertext and signatures produced under them keep decrypting and verifying. Decrypt reads the version out of the blob and uses the matching material automatically.
Signing
A sign key produces sg1. signatures over any message. Verification only needs
the published public key for the signature's version, so a verifier needs org
membership but not a grant — sign with a tightly-held key, verify anywhere.
What the server sees
For an encrypt key the server stores the AES key only as wd1. grants; for a
sign key it stores the wrapped PKCS8 private key as grants and the public
key per version. It never sees the plaintext key material, the values you
encrypt, or the messages you sign — those exist only in the client that holds a
grant. A full database dump yields ciphertext, public keys, and grant rows.
When to use a KMS key vs. a secret
Reach for a secret to store a config value (a database URL, an API key) that a process reads at boot. Reach for a KMS key when your application does its own cryptography — encrypting a database column or file, minting an envelope data key, or signing an artifact or token — and you want the key centrally managed, grantable, rotatable, and audited without ever exposing it.