keystore

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Aug 28, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package keystore provides secure storage for API keys.

Index

Constants

View Source
const DefaultMasterKeyEnvVar = "IRIS_KEYSTORE_KEY"

DefaultMasterKeyEnvVar is the environment variable name for the master key.

Variables

View Source
var ErrMasterKeyRequired = errors.New("master key required for keystore operation")

ErrMasterKeyRequired is returned when a master key is needed but not provided.

Functions

func DefaultKeystorePath

func DefaultKeystorePath() string

DefaultKeystorePath returns the default keystore file path. - macOS/Linux: ~/.iris/keys.enc - Windows: %USERPROFILE%\.iris\keys.enc

Types

type EnvMasterKeySource added in v0.10.0

type EnvMasterKeySource struct {
	EnvVar string
}

EnvMasterKeySource provides the master key from an environment variable.

func (*EnvMasterKeySource) GetMasterKey added in v0.10.0

func (s *EnvMasterKeySource) GetMasterKey() ([]byte, error)

GetMasterKey returns the master key from the configured environment variable.

type ErrKeyNotFound

type ErrKeyNotFound struct {
	Name string
}

ErrKeyNotFound is returned when a requested key does not exist.

func (*ErrKeyNotFound) Error

func (e *ErrKeyNotFound) Error() string

type FallbackMasterKeySource added in v0.10.0

type FallbackMasterKeySource struct {
	Sources []MasterKeySource
}

FallbackMasterKeySource tries multiple sources in order.

func (*FallbackMasterKeySource) GetMasterKey added in v0.10.0

func (s *FallbackMasterKeySource) GetMasterKey() ([]byte, error)

GetMasterKey tries each source in order until one succeeds.

type FileKeystore

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

FileKeystore implements Keystore using encrypted file storage. Keys are stored in a JSON map encrypted with AES-256-GCM. v2 format uses Argon2id for key derivation from a master key.

func NewFileKeystore

func NewFileKeystore(path string) (*FileKeystore, error)

NewFileKeystore creates a new file-based keystore at the given path. The encryption key is derived from machine-specific data (v1 legacy mode). For production use, prefer NewFileKeystoreWithSource.

func NewFileKeystoreWithSource added in v0.10.0

func NewFileKeystoreWithSource(path string, source MasterKeySource) (*FileKeystore, error)

NewFileKeystoreWithSource creates a new file-based keystore with a master key source. This is the recommended way to create a keystore for production use.

func (*FileKeystore) Delete

func (f *FileKeystore) Delete(name string) error

Delete removes a key by name.

func (*FileKeystore) Get

func (f *FileKeystore) Get(name string) (string, error)

Get retrieves a value by name.

func (*FileKeystore) IsV2Format added in v0.10.0

func (f *FileKeystore) IsV2Format() (bool, error)

IsV2Format checks if the keystore file is in v2 format.

func (*FileKeystore) List

func (f *FileKeystore) List() ([]string, error)

List returns all stored key names.

func (*FileKeystore) MigrateToV2 added in v0.10.0

func (f *FileKeystore) MigrateToV2() (MigrateResult, error)

MigrateToV2 migrates a legacy keystore to v2 format encrypted under this keystore's master key. It handles both v1-format files and v2-format files encrypted with the legacy machine-derived key (requires WithLegacyKeyFallback, which NewKeystore enables automatically). The original file is preserved at <path>.bak before the new one is written. The call is idempotent: an already-current store returns MigrateAlreadyCurrent.

func (*FileKeystore) NeedsMigration added in v1.0.0

func (f *FileKeystore) NeedsMigration() (bool, error)

NeedsMigration reports whether the store file cannot be decrypted with the current master key alone, meaning it is v1-format or was encrypted under the legacy machine-derived key. Running MigrateToV2 re-encrypts it.

func (*FileKeystore) Path added in v1.0.0

func (f *FileKeystore) Path() string

Path returns the keystore file path.

func (*FileKeystore) Set

func (f *FileKeystore) Set(name, value string) error

Set stores a key-value pair.

func (*FileKeystore) UsesLegacyKey added in v1.0.0

func (f *FileKeystore) UsesLegacyKey() bool

UsesLegacyKey reports whether the keystore was opened with the insecure machine-derived v1 key (i.e., no master key source was provided).

func (*FileKeystore) WithLegacyKeyFallback added in v1.0.0

func (f *FileKeystore) WithLegacyKeyFallback() *FileKeystore

WithLegacyKeyFallback enables reading stores encrypted by older versions: v1-format files and v2-format files keyed with the machine-derived legacy key. Decryption is attempted with the master key first; the legacy key is only tried when that fails. Writes always use the master key, so any Set or Delete transparently re-encrypts the store.

type Keystore

type Keystore interface {
	// Set stores a key-value pair.
	Set(name, value string) error
	// Get retrieves a value by name. Returns error if not found.
	Get(name string) (string, error)
	// Delete removes a key by name.
	Delete(name string) error
	// List returns all stored key names.
	List() ([]string, error)
}

Keystore defines the interface for secure key storage.

func NewKeystore

func NewKeystore() (Keystore, error)

NewKeystore creates a new keystore using file-based encrypted storage.

It is master-key aware: when DefaultMasterKeyEnvVar (IRIS_KEYSTORE_KEY) is set, the store is encrypted with that master key (v2 format, Argon2id + AES-256-GCM) and legacy stores written by older versions remain readable via a decryption fallback, so they can be migrated with MigrateToV2 (or transparently on the next write). When the environment variable is not set, it falls back to the legacy machine-derived key (v1 mode), which is convenient for development but predictable; callers can detect this via FileKeystore.UsesLegacyKey.

func NewKeystoreAtPath added in v1.0.0

func NewKeystoreAtPath(path string) (Keystore, error)

NewKeystoreAtPath is like NewKeystore but opens the store at path.

type MasterKeySource added in v0.10.0

type MasterKeySource interface {
	// GetMasterKey returns the master key for encryption/decryption.
	// Returns an error if the key cannot be obtained.
	GetMasterKey() ([]byte, error)
}

MasterKeySource provides the encryption master key. Implementations can source the key from various places (env var, prompt, etc.).

type MigrateResult added in v1.0.0

type MigrateResult int

MigrateResult reports the outcome of a MigrateToV2 call.

const (
	// MigrateNone means no keystore file existed (or it was empty).
	MigrateNone MigrateResult = iota
	// MigrateAlreadyCurrent means the store is already v2-format and
	// encrypted under the current master key.
	MigrateAlreadyCurrent
	// MigrateRekeyed means the store was decrypted (via the master key or the
	// legacy fallback) and re-encrypted under the current master key.
	MigrateRekeyed
)

type PromptMasterKeySource added in v0.10.0

type PromptMasterKeySource struct {
	Prompter func(prompt string) ([]byte, error)
}

PromptMasterKeySource provides the master key via interactive prompt.

func (*PromptMasterKeySource) GetMasterKey added in v0.10.0

func (s *PromptMasterKeySource) GetMasterKey() ([]byte, error)

GetMasterKey prompts the user for the master key.

Jump to

Keyboard shortcuts

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