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
- Variables
- func ConfirmPresence(string) error
- func EnvPasswordValue(getenv func(string) string) ([]byte, bool, error)
- func PresenceAvailable() error
- func WriteFileAtomic(path string, data []byte, perm os.FileMode) error
- type KDF
- type KeyFile
- func (kf *KeyFile) AddKeyringSlot(root []byte, kr Keyring, touchID bool) (string, error)
- func (kf *KeyFile) AddPasswordSlot(root, password []byte, params skcrypto.Argon2Params) (string, error)
- func (kf *KeyFile) HasPlainKeyring() bool
- func (kf *KeyFile) HasSlot(typ string) bool
- func (kf *KeyFile) RemoveSlot(id string, kr Keyring) error
- func (kf *KeyFile) Save(path string) error
- func (kf *KeyFile) UnlockKeyring(kr Keyring, confirm func() error) (root []byte, touchID bool, err error)
- func (kf *KeyFile) UnlockPassword(password []byte) ([]byte, error)
- type Keyring
- type KeyringRef
- type MemoryKeyring
- type OSKeyring
- type Slot
- type Unlocker
Constants ¶
const ( SlotPassword = "password" SlotKeyring = "keyring" )
Slot types.
const ( EnvPassword = "SSLKNIFE_PASSWORD" EnvPasswordFile = "SSLKNIFE_PASSWORD_FILE" )
Environment variables for non-interactive unlocking (CI, containers).
const ( MethodEnv = "environment" MethodCache = "cache" MethodKeyring = "keychain" MethodTouchID = "touch-id" MethodPrompt = "password" )
Method names reported by Unlock.
const KeyringService = "sslknife"
KeyringService is the service name used for OS keychain entries.
Variables ¶
var ErrBadPassword = errors.New("incorrect vault password")
ErrBadPassword means no password slot accepted the supplied password.
var ErrKeyringNotFound = errors.New("keychain entry not found")
ErrKeyringNotFound is returned when the entry does not exist.
var ErrLocked = errors.New("vault is locked: set " + EnvPassword + " or " + EnvPasswordFile + ", or run in a terminal")
ErrLocked means no unlock method was available.
var ErrNoSlot = errors.New("no matching keyslot")
ErrNoSlot means the key file has no slot of the requested type.
var ErrPresenceDenied = errors.New("presence confirmation with Touch ID failed")
ErrPresenceDenied means the user cancelled or failed the confirmation.
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
ConfirmPresence is unavailable outside macOS.
func EnvPasswordValue ¶
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.
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 ¶
LoadKeyFile reads and validates a key file.
func NewKeyFile ¶
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 ¶
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
HasPlainKeyring reports whether a keychain slot without Touch ID exists.
func (*KeyFile) RemoveSlot ¶
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) 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.
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 ¶
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
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.
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.