secrets

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Oct 2, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package secrets manages the vault root key: the keyslot file that stores it wrapped under password- or keychain-derived keys, and the providers used to unlock it (environment, OS keychain, TTY).

Index

Constants

View Source
const (
	SlotPassword = "password"
	SlotKeyring  = "keyring"
)

Slot types.

View Source
const (
	EnvPassword     = "SSLKNIFE_PASSWORD"
	EnvPasswordFile = "SSLKNIFE_PASSWORD_FILE"
)

Environment variables for non-interactive unlocking (CI, containers).

View Source
const (
	MethodEnv     = "environment"
	MethodCache   = "cache"
	MethodKeyring = "keychain"
	MethodTouchID = "touch-id"
	MethodPrompt  = "password"
)

Method names reported by Unlock.

View Source
const KeyringService = "sslknife"

KeyringService is the service name used for OS keychain entries.

Variables

View Source
var ErrBadPassword = errors.New("incorrect vault password")

ErrBadPassword means no password slot accepted the supplied password.

View Source
var ErrKeyringNotFound = errors.New("keychain entry not found")

ErrKeyringNotFound is returned when the entry does not exist.

View Source
var ErrLocked = errors.New("vault is locked: set " + EnvPassword + " or " + EnvPasswordFile + ", or run in a terminal")

ErrLocked means no unlock method was available.

View Source
var ErrNoSlot = errors.New("no matching keyslot")

ErrNoSlot means the key file has no slot of the requested type.

View Source
var ErrPresenceDenied = errors.New("presence confirmation with Touch ID failed")

ErrPresenceDenied means the user cancelled or failed the confirmation.

View Source
var ErrPresenceUnavailable = errors.New("presence confirmation with Touch ID requires macOS")

ErrPresenceUnavailable means this system cannot confirm user presence (Touch ID, Apple Watch) for keychain slots that require it.

Functions

func ConfirmPresence added in v0.2.0

func ConfirmPresence(string) error

ConfirmPresence is unavailable outside macOS.

func EnvPasswordValue

func EnvPasswordValue(getenv func(string) string) ([]byte, bool, error)

EnvPasswordValue returns the password from the environment, if any. A password file has one trailing newline trimmed.

func PresenceAvailable added in v0.2.0

func PresenceAvailable() error

PresenceAvailable reports whether ConfirmPresence can prompt; only macOS supports it.

func WriteFileAtomic

func WriteFileAtomic(path string, data []byte, perm os.FileMode) error

WriteFileAtomic writes data to a temporary file in the same directory and renames it over path, so readers never observe a partial file.

Types

type KDF

type KDF struct {
	Name   string                `json:"name"`
	Salt   []byte                `json:"salt"`
	Params skcrypto.Argon2Params `json:"params"`
}

KDF describes how a password slot's KEK is derived.

type KeyFile

type KeyFile struct {
	Version int       `json:"version"`
	DBID    string    `json:"db_id"`
	Created time.Time `json:"created"`
	Slots   []Slot    `json:"slots"`
}

KeyFile is the JSON document stored next to the database. It never contains the root key in plaintext.

func LoadKeyFile

func LoadKeyFile(path string) (*KeyFile, error)

LoadKeyFile reads and validates a key file.

func NewKeyFile

func NewKeyFile() (*KeyFile, []byte)

NewKeyFile creates a key file for a new vault and returns the freshly generated root key. The caller must add at least one slot before saving.

func (*KeyFile) AddKeyringSlot

func (kf *KeyFile) AddKeyringSlot(root []byte, kr Keyring, touchID bool) (string, error)

AddKeyringSlot stores a random KEK in the OS keychain and wraps root under it. With touchID the slot is only used after ConfirmPresence succeeds.

func (*KeyFile) AddPasswordSlot

func (kf *KeyFile) AddPasswordSlot(root, password []byte, params skcrypto.Argon2Params) (string, error)

AddPasswordSlot wraps root under a key derived from password.

func (*KeyFile) HasPlainKeyring added in v0.2.0

func (kf *KeyFile) HasPlainKeyring() bool

HasPlainKeyring reports whether a keychain slot without Touch ID exists.

func (*KeyFile) HasSlot

func (kf *KeyFile) HasSlot(typ string) bool

HasSlot reports whether a slot of type exists.

func (*KeyFile) RemoveSlot

func (kf *KeyFile) RemoveSlot(id string, kr Keyring) error

RemoveSlot deletes a slot by ID. The last slot cannot be removed because that would make the vault permanently inaccessible. Keychain entries are deleted when kr is non-nil.

func (*KeyFile) Save

func (kf *KeyFile) Save(path string) error

Save writes the key file atomically with mode 0600.

func (*KeyFile) UnlockKeyring

func (kf *KeyFile) UnlockKeyring(kr Keyring, confirm func() error) (root []byte, touchID bool, err error)

UnlockKeyring tries every keychain slot, plain slots first. Touch ID slots are tried only after confirm succeeds; confirm is called at most once, and a nil confirm skips them. touchID reports which kind worked.

func (*KeyFile) UnlockPassword

func (kf *KeyFile) UnlockPassword(password []byte) ([]byte, error)

UnlockPassword tries every password slot.

type Keyring

type Keyring interface {
	Get(service, account string) ([]byte, error)
	Set(service, account string, secret []byte) error
	Delete(service, account string) error
}

Keyring stores small secrets in an OS credential store.

type KeyringRef

type KeyringRef struct {
	Service string `json:"service"`
	Account string `json:"account"`
}

KeyringRef locates a slot's KEK in the OS keychain.

type MemoryKeyring

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

MemoryKeyring is an in-process keyring for tests.

func (*MemoryKeyring) Delete

func (k *MemoryKeyring) Delete(service, account string) error

func (*MemoryKeyring) Get

func (k *MemoryKeyring) Get(service, account string) ([]byte, error)

func (*MemoryKeyring) Set

func (k *MemoryKeyring) Set(service, account string, secret []byte) error

type OSKeyring

type OSKeyring struct{}

OSKeyring uses macOS Keychain, Windows Credential Manager or the freedesktop Secret Service. Values are hex-encoded because some backends only store text.

func (OSKeyring) Delete

func (OSKeyring) Delete(service, account string) error

func (OSKeyring) Get

func (OSKeyring) Get(service, account string) ([]byte, error)

func (OSKeyring) Set

func (OSKeyring) Set(service, account string, secret []byte) error

type Slot

type Slot struct {
	ID      string      `json:"id"`
	Type    string      `json:"type"`
	Created time.Time   `json:"created"`
	KDF     *KDF        `json:"kdf,omitempty"`
	Keyring *KeyringRef `json:"keyring,omitempty"`
	// TouchID makes a keychain slot usable only after the user confirms
	// with Touch ID or Apple Watch (macOS).
	TouchID bool   `json:"touch_id,omitempty"`
	Nonce   []byte `json:"nonce"`
	Wrapped []byte `json:"wrapped"`
}

Slot wraps the root key under one key-encryption key.

type Unlocker

type Unlocker struct {
	Getenv  func(string) string
	Cache   func(dbID string) ([]byte, error) // nil disables the unlock cache
	Keyring Keyring                           // nil disables keychain unlocking
	// Presence confirms the user for Touch ID keychain slots; nil skips them.
	Presence func() error
	Prompt   func() ([]byte, error) // nil disables prompting
}

Unlocker tries the configured unlock methods in order: environment, unlock cache, keychain (plain, then Touch ID), interactive prompt.

func (Unlocker) Unlock

func (u Unlocker) Unlock(kf *KeyFile) ([]byte, string, error)

Unlock returns the root key and the method that produced it.

Jump to

Keyboard shortcuts

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