secret

package
v0.4.13 Latest Latest
Warning

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

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

Documentation

Overview

Package secret holds the two secrecy primitives the whole binary depends on: the Redacted type (a value that refuses to serialize itself in the clear) and the AES-256-GCM Cipher used for secrets at rest (plan §5.5).

Custom lint rule (CONTRIBUTING / plan §15): any type that holds a secret must have String()/MarshalJSON that return the redaction marker. Redacted is the canonical implementation; reach for it instead of a bare string.

Index

Constants

View Source
const Marker = "••••" // ••••

Marker is what a redacted value renders as anywhere it might be logged.

Variables

View Source
var (
	// ErrDecrypt is returned for any open failure. It is intentionally opaque so
	// it cannot become a decryption oracle.
	ErrDecrypt = errors.New("secret: decryption failed")
	// ErrKeyLen is returned when a key is not exactly 32 bytes.
	ErrKeyLen = errors.New("secret: key must be 32 bytes (AES-256)")
)

Functions

This section is empty.

Types

type Cipher

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

Cipher seals/opens blobs with AES-256-GCM. It optionally holds a previous key so a rotation (encryption_key_previous, plan §5.5) can still open old rows; Seal always uses the current key.

func NewCipher

func NewCipher(key, prevKey []byte) (*Cipher, error)

NewCipher builds a Cipher from the current key and an optional previous key (pass nil/empty when not rotating).

func (*Cipher) Open

func (c *Cipher) Open(blob []byte) ([]byte, error)

Open decrypts a blob, trying the current key then the previous key.

func (*Cipher) Seal

func (c *Cipher) Seal(plaintext []byte) ([]byte, error)

Seal encrypts plaintext under the current key. Output is nonce||ciphertext+tag.

type Redacted

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

Redacted wraps a secret string. Its String/MarshalJSON/MarshalText/GoString all return the redaction marker, so a secret can never leak into a log line, an error, a JSON response, %v/%+v/%#v formatting, or a template by accident. Reveal() is the single, greppable place the plaintext escapes.

func New

func New(s string) Redacted

New wraps a plaintext secret.

func (Redacted) Equal

func (r Redacted) Equal(candidate string) bool

Equal compares the secret to a candidate in constant time.

func (Redacted) Format

func (r Redacted) Format(f fmt.State, verb rune)

Format implements fmt.Formatter so EVERY verb — including numeric/other verbs like %d/%x/%g that fmt would otherwise satisfy via reflection over the unexported field — routes through the redaction marker. Without this, a wrong-verb format string (e.g. `%d`) would print the plaintext (review #5).

func (Redacted) GoString

func (r Redacted) GoString() string

GoString covers the %#v verb.

func (Redacted) IsZero

func (r Redacted) IsZero() bool

IsZero reports whether the secret is empty.

func (Redacted) MarshalJSON

func (r Redacted) MarshalJSON() ([]byte, error)

MarshalJSON ensures encoding/json never emits the plaintext.

func (Redacted) MarshalText

func (r Redacted) MarshalText() ([]byte, error)

MarshalText covers encoders that prefer TextMarshaler (incl. some YAML paths).

func (Redacted) Reveal

func (r Redacted) Reveal() string

Reveal returns the underlying plaintext. This is the only API that does so; every call site is intentionally easy to audit (grep for ".Reveal(").

func (Redacted) String

func (r Redacted) String() string

String returns the redaction marker (empty stays empty so we never imply a secret exists where one does not).

Jump to

Keyboard shortcuts

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