secrets

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 6, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package secrets owns at-rest encryption for sensitive values stored in the local SQLite DB — the Mailtrap cloud API token, the SMTP relay password, the webhook signing secret.

Threat model: a localhost-only dev tool. The DB file may end up in backups, disk images, or accidentally-shared `data/` directories. Plaintext credentials in there are bad. The encryption is **defense in depth** — anyone with simultaneous read access to both the DB file *and* the key file can still decrypt. We don't pretend otherwise. The win is that a casual `cp data/*.sqlite3` doesn't leak credentials by itself.

Crypto: AES-256-GCM. Key = 32 random bytes auto-generated on first use, persisted at ${XDG_CONFIG_HOME:-~/.config}/mailtrap-local/secret.key (override with $MAILTRAP_LOCAL_SECRET_KEY_FILE). Mode 0600.

Wire format on disk: "enc:v1:<base64(nonce|ciphertext|tag)>" We prefix with "enc:v1:" so the read path can tell encrypted bytes from legacy plaintext (rows written by older binaries) and migrate transparently on next write.

Index

Constants

View Source
const Prefix = "enc:v1:"

Prefix marks a stored value as encrypted. Read code that doesn't see this prefix should treat the value as legacy plaintext (and re-encrypt on next write to migrate it forward).

Variables

This section is empty.

Functions

func DefaultKeyPath

func DefaultKeyPath() (string, error)

DefaultKeyPath returns the file the binary auto-generates a key at on first use, unless overridden by $MAILTRAP_LOCAL_SECRET_KEY_FILE.

$MAILTRAP_LOCAL_SECRET_KEY_FILE                 — explicit override
$XDG_CONFIG_HOME/mailtrap-local/secret.key      — XDG-respecting default
~/.config/mailtrap-local/secret.key             — fallback

func IsEncrypted

func IsEncrypted(stored string) bool

IsEncrypted reports whether `stored` is in the encrypted wire format. Useful for migration logic ("if !IsEncrypted, re-encrypt on next write").

func LoadOrCreateKey

func LoadOrCreateKey(path string) ([]byte, error)

Types

type Box

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

func FromDefaultKeyFile

func FromDefaultKeyFile() (*Box, error)

FromDefaultKeyFile is the most-common entrypoint: resolve the key path, ensure a key exists, return a ready-to-use Box.

func New

func New(key []byte) (*Box, error)

New constructs a Box from a 32-byte key.

func (*Box) Decrypt

func (b *Box) Decrypt(stored string) (string, error)

Decrypt reverses Encrypt. Values without Prefix are treated as legacy plaintext and returned as-is — the caller can detect the migration case by also checking IsEncrypted.

func (*Box) Encrypt

func (b *Box) Encrypt(plaintext string) (string, error)

Encrypt returns Prefix+base64(nonce|ciphertext|tag). Empty strings pass through unchanged so callers don't need to special-case the "no value set" path.

Jump to

Keyboard shortcuts

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