Encryption

Updated

Kryptic is a blind store. Secret values are encrypted on the client (browser, daemon, or CI runner) under a 256-bit organization key that exists in plaintext only on clients. The server stores and serves ciphertext it has no path to open. The wire-level writeup (envelopes, sealed boxes, who decrypts when) is For geeks.

This is the licensing boundary as well: anything that can see a secret in plaintext is open source. The server platform is proprietary because it never holds a key that would let it read your values.

What the server can and cannot see

MaterialWho can open it
Secret envelopes (v1.<orgKeyId>.…)Anyone holding the org key: an unlocked browser vault, an approved daemon device, a granted machine identity
Org-key grants (P-256 sealed boxes)The recipient whose public key the grant was sealed to
Operational ciphertexts (SSO IdP client secrets, directory credentials)The server, under a separate data key wrapped by MASTER_KEY

Losing MASTER_KEY on a self-hosted install breaks those operational ciphertexts (SSO secrets and similar). It does not decrypt, or prevent clients from decrypting, customer secret values. Those live under the org key. Back MASTER_KEY up anyway: without it you cannot re-read the platform's own stored IdP credentials.

Organization key

An Owner or Admin initializes encryption in Settings → Encryption. The browser generates the org key, wraps a copy to the admin's vault, and shows a one-time recovery code (Emergency Kit). Later recipients (other members' vaults, approved daemon devices, machine identities) receive the org key as a sealed-box grant. An admin approves pending grants from Approvals (or from Device right after a daemon login). Unlock the vault first. Encryption setup stays on Settings → Encryption.

The vault passphrase is not the login password. Members with a local password change that password on Settings → Account. Change the vault passphrase on Settings → Encryption while the vault is unlocked: the same private key is re-wrapped, so existing grants stay valid. A forgotten vault passphrase cannot be reset. Creating a new vault key is a new key pair. An admin must grant the organization key again.

Rotation is client-side: the admin's browser generates a fresh key, re-encrypts current values locally, and re-grants active recipients atomically. Recommended after removing a member.

The three engines

The wire formats (AES-256-GCM envelopes, P-256 sealed boxes, Argon2id) are implemented three times so every runtime that touches plaintext uses the same bytes. A format change must land in all three repositories in the same release; interop-vectors/ in each repo is the contract.

RepositoryRuntimeConsumed byPackage
Kryptic.Encryption.Net.NETKryptic Platform (operational ciphertexts only)NuGet Kryptic.Encryption
Kryptic.Encryption.NPMTypeScript / WebCryptoManagement dashboardnpm @krypticdev/encryption
Kryptic.Encryption.GoGoDaemon, CLI (kryptic ci export), Kubernetes operatorGo module github.com/dev-kryptic/Kryptic.Encryption.Go

No custom primitives. AES-256-GCM and P-256 ECDH come from platform cryptography (.NET System.Security.Cryptography, browser WebCrypto, Go crypto/ecdh). Argon2id comes from proven libraries. Each engine ships a SECURITY.md describing the key hierarchy.

Language SDKs never decrypt. They ask the local daemon over a unix socket or named pipe; the daemon already holds plaintext in memory after opening the bundle with the Go engine.

Do not send secret values to the REST API or Pipelines BFF as plaintext. Writes accept envelopes you encrypted locally. Reads return envelopes plus a wrappedOrgKey sealed to the caller. See REST API v1 and kryptic ci export.