enc

package
v0.8.3 Latest Latest
Warning

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

Go to latest
Published: May 6, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package enc implements wick's encrypted-fields layer: a per-user AES-256-GCM cipher that lets credentials and other sensitive values flow between an LLM and a connector without ever appearing as plaintext in the LLM's context window or in audit logs.

The wire format is a single token with a fixed prefix:

wick_enc_<base64url(nonce ‖ AES-256-GCM(plaintext, nonce, derived_key))>

The 32-byte derived key is per-user — HKDF(master_key, salt=user_uuid, info="wick-enc") — so a token issued for user A cannot be decrypted when user B replays it.

Two operation modes:

  • Mask(data, values, user) — replaces every occurrence of each plaintext value in data with its wick_enc_ token, sharing one token per identical plaintext within the same call so the LLM does not mistake duplicates for distinct credentials.
  • Unmask(data, user) — inverse: scans data for wick_enc_ tokens and replaces each with its plaintext.

Disabled() reports whether WICK_ENC_DISABLE is set — when true, callers should skip mask/unmask and pass values through unchanged.

Index

Constants

View Source
const MasterPrefix = "wick_cenc_"

MasterPrefix marks a config-encrypted token (at-rest, master-key keyed, no per-user salt). Distinct from Prefix so the wrong decrypt path can't pick it up — Mask/Unmask scan only for Prefix.

View Source
const Prefix = "wick_enc_"

Prefix marks an encrypted token in user-visible payloads. The string is intentionally distinct from any other format wick or common upstream APIs emit, so a substring scan is unambiguous.

Variables

View Source
var ErrNotToken = errors.New("enc: not a wick_enc_ token")

ErrNotToken signals that DecryptValue saw something that does not carry the wick_enc_ prefix. Callers that scan free-form text for embedded tokens use IsToken first; this error is for direct callers that expected a token.

Functions

func IsMasterToken added in v0.6.1

func IsMasterToken(s string) bool

IsMasterToken reports whether s carries the wick_cenc_ prefix used for at-rest config encryption. Distinct from IsToken so callers can pick the right decrypt path (master vs per-user).

func IsToken

func IsToken(s string) bool

IsToken reports whether s begins with the wick_enc_ prefix. Cheap — callers can use it to skip the work of decoding when they're not sure what they're holding.

Types

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service wraps the master key + the per-user key derivation. One instance is shared across the process; methods are safe to call concurrently.

func New

func New(masterKeyHex string) (*Service, error)

New constructs a Service from a hex-encoded 32-byte master key. An empty key (or one of the wrong length) returns an error so the boot path can fail loudly rather than silently disabling encryption.

When WICK_ENC_DISABLE=true is set in the environment, the returned Service is valid but Disabled() returns true; callers MUST short- circuit on that flag rather than letting empty/zero crypto run.

func (*Service) DecryptMaster added in v0.6.1

func (s *Service) DecryptMaster(token string) (string, error)

DecryptMaster reverses EncryptMaster. Returns ErrNotToken when the input lacks the wick_cenc_ prefix. The error is opaque on auth/decrypt failure (typically: master key was rotated since the token was written).

func (*Service) DecryptValue

func (s *Service) DecryptValue(token, userUUID string) (string, error)

DecryptValue reverses EncryptValue. Returns ErrNotToken when the input lacks the wick_enc_ prefix and an opaque error when the token is malformed or the key is wrong (e.g. cross-user replay).

func (*Service) Disabled

func (s *Service) Disabled() bool

Disabled reports whether encryption is opt-out via the env var. When true, Mask/Unmask return data unchanged and EncryptValue/DecryptValue refuse to operate.

func (*Service) EncryptMaster added in v0.6.1

func (s *Service) EncryptMaster(plain string) (string, error)

EncryptMaster produces a wick_cenc_ token bound to the master key (no per-user salt). Used for at-rest config encryption: admin pastes plaintext into a `secret`-tagged config row, the configs service stores the token, and DecryptMaster restores the plaintext when the row is read back into the cache.

Disabled service is a programmer error — the configs layer must not call this when Disabled() is true. Returns an error rather than silently passing through.

func (*Service) EncryptValue

func (s *Service) EncryptValue(plain, userUUID string) (string, error)

EncryptValue produces one wick_enc_ token for the given plaintext. Returns the original string when the service is disabled. No length floor — admin opted in (manual UI) or tagged the field as secret/encrypt (auto-mask), so short values are honored either way. Pick distinct, non-generic values for sensitive fields to avoid false-positive substring hits during the auto-mask scan.

func (*Service) Mask

func (s *Service) Mask(data string, values []string, userUUID string) string

Mask replaces every occurrence of every value in `values` inside `data` with its wick_enc_ token. Identical values receive identical tokens within one call — the per-call cache guarantees the LLM does not see two distinct ciphertexts for the same secret and conclude they are different secrets.

When the service is disabled, returns data unchanged.

func (*Service) MaskIgnoreCase

func (s *Service) MaskIgnoreCase(data string, values []string, userUUID string) string

MaskIgnoreCase is the case-insensitive variant of Mask. Every case variant of a keyword in `data` is replaced with a single token derived from the keyword's configured form (so the LLM, when it passes the token back, gets the configured spelling on decrypt). Keywords that differ only in case share one token via a lowercased cache key.

Implementation uses regexp with the (?i) flag and quotes the keyword so regex metacharacters in user-supplied values are matched literally.

func (*Service) Unmask

func (s *Service) Unmask(data, userUUID string) (string, error)

Unmask scans data for wick_enc_ tokens and replaces each with its plaintext. Returns an error when ANY token fails to decrypt (typically: the key was rotated since the token was issued, or the token was issued for a different user). Tokens are de-duplicated so repeated occurrences only pay decryption cost once.

When the service is disabled, returns data unchanged with no error.

Jump to

Keyboard shortcuts

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