cek

package
v1.801.218 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 26, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package cek is cloud's ONE encryption-at-rest gate for its per-subsystem SQLite stores. Every store opens its database through cek.Open — the single seam where a plaintext file is transparently migrated to SQLCipher and a keyed *sql.DB is returned — so "encrypted at rest" is a property of the open path, not something each of the ~30 stores must remember to do.

THREAT MODEL. The DO block volume under /var/lib/cloud is provider-encrypted, so the residual exposure is a COPIED PV snapshot/backup or an in-cluster exec/PV read seeing plaintext customer PII (crm), the ledger (treasury), org wallet maps (wallets), the audit log, team/entitlements. cek removes that exposure: each file's pages are SQLCipher-encrypted under a per-database key that never leaves the process in the clear and is itself wrapped by the KMS-injected master key; the pre-migration plaintext copy is shredded once the encrypted store is proven readable. A lifted file is useless without the key.

SCOPE / NON-GOALS. cek provides CONFIDENTIALITY at rest against the read-only exposure above (no master key ⇒ no plaintext). It is NOT integrity, authenticity, or anti-rollback against a PV-WRITE (node-compromise) adversary who can modify the volume: the per-file id lives in the (unauthenticated) .dek sidecar, so such an adversary could swap two of OUR OWN {db,.dek} pairs or replay an old snapshot. That is outside the stated model and is deliberately NOT defended here (a logical-id+epoch binding would add complexity for an out-of-model threat); revisit only if tenant-isolation-under-node-compromise is scoped in.

ENVELOPE (the primitives live in github.com/hanzoai/sqlite/cek.go and are reused verbatim — one crypto implementation, KAT-gated there):

  • Each database has its OWN random 256-bit DEK (the SQLCipher page key), minted once at first touch and NEVER changed, so ciphertext pages are never rewritten.
  • Each database also gets a random 128-bit FILE ID, stored in the clear at the head of its <db>.dek sidecar. The KEK is derived from that id, NOT the file path: KEK = HKDF-SHA256(masterKey, lp("global") || lp(hex(fileID))). The id is intrinsic to the file and travels with the sidecar, so moving the data dir or changing CLOUD_DATA_DIR can never change the KEK and brick a store. RFC-5869 HKDF via x/crypto/hkdf — NOT luxfi/crypto/kdf (a QZMQ KeySchedule, not generic HKDF; using it would brick every store).
  • The DEK is wrapped AES-256-GCM under the KEK, bound to the same id as AAD. Sidecar = fileID(16) || wrapped-DEK. The raw DEK is never written.
  • Master-key ROTATION rewraps only the sidecar: the DEK and fileID are unchanged, so no page is rewritten and no file can be bricked.

FAIL-SECURE. On an encryption-CAPABLE build (production is CGO + libsqlcipher) a missing master key is FATAL — the data plane refuses to open unencrypted, the same posture the KMS store takes. A key set on a NON-encrypting build is likewise fatal. An encrypted file whose sidecar is missing is refused. A migration whose encrypted copy does not reproduce the source's schema AND per-table content (a rowid-independent multiset hash, not just a row count) leaves the plaintext untouched and errors — the caller (MountAll) fails closed, so cloud never serves a half-migrated data plane.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Encrypting

func Encrypting() bool

Encrypting reports whether cek will encrypt at rest (a valid master key is configured on an encryption-capable build). cloud calls this once at boot for the posture log; a false result on a capable build means resolveMaster errored and the first store Open will fail closed.

func Open

func Open(path string) (*sql.DB, error)

Open returns a *sql.DB for the SQLite database at path, encrypted at rest when a master key is configured. It is the single drop-in replacement for sql.Open("sqlite", path) across every cloud store.

func SetMasterKey

func SetMasterKey(k []byte)

SetMasterKey injects the 32-byte master key explicitly (cloud's boot resolves it once from cfg and hands it here), taking precedence over the environment. Call before the first Open. A wrong-length key is ignored so the env path can still apply.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL