// Package envelope - envelope encryption of secrets at rest. // // Secrets are protected with a two-layer scheme: // // - A Data Encryption Key (DEK) is generated per tenant and stored in the // database, itself encrypted ("wrapped") by a Key Encryption Key (KEK), so // the database never holds a plaintext key. // // - The KEK is managed by a [Wrapper] and never touches the database. The // Wrapper abstracts over how the KEK is stored and used: a local key file // for development, or an external service such as AWS KMS or HashiCorp // Vault in production. // // The application-facing surface is sealing, not raw keys. A // [TenantEncryptor], built by [EncryptorFactory.For] once a tenant's DEK is // unwrapped, encrypts with Seal (returning the DEK id and ciphertext to store // as columns) and decrypts with Open. The ciphertext carries a magic header, // so [IsSealed] lets storage code reject plaintext before persisting it. DEKs // are minted at tenant-provisioning time with [EncryptorFactory.Provision], // never lazily. // // [KeyFile] is the provided Wrapper: a 32-byte AES-256-GCM key stored as hex // on disk, for development and demo use only. In production, use a Wrapper // backed by a key management service so the KEK never exists as plaintext in // the application process. package envelope import "context" // Wrapper wraps and unwraps data encryption keys using a key encryption key. // The blobs returned by Wrap are opaque; their format is implementation-defined. type Wrapper interface { Wrap(ctx context.Context, dek []byte) ([]byte, error) Unwrap(ctx context.Context, blob []byte) ([]byte, error) }