check / check (push) Failing after 2s
Keychain and Secure Enclave unlocker IDs were the creation time to the minute plus the host name, and passphrase unlocker IDs the time to the minute, so two created within one minute shared an ID, and `unlocker select`, `unlocker remove` and the selection after `unlocker add` acted on the older one. Every unlocker's ID is now its directory name, unique in its vault. `vault.ListUnlockers` returns each unlocker's metadata keyed by that name, so `unlocker list` and shell completion no longer find IDs by matching metadata. PGP unlocker IDs were `pgp-<fingerprint>`; a second PGP unlocker for one key is refused by comparing fingerprints in metadata. Model: opus-5-5
89 lines
2.1 KiB
Go
89 lines
2.1 KiB
Go
//go:build !darwin
|
|
|
|
package secret
|
|
|
|
import (
|
|
"errors"
|
|
"path/filepath"
|
|
|
|
"filippo.io/age"
|
|
"github.com/awnumar/memguard"
|
|
"github.com/spf13/afero"
|
|
)
|
|
|
|
// seUnlockerType is the type string for Secure Enclave unlockers.
|
|
const seUnlockerType = "secure-enclave"
|
|
|
|
var errSENotSupported = errors.New(
|
|
"secure enclave unlockers are only supported on macOS",
|
|
)
|
|
|
|
// SecureEnclaveUnlockerMetadata is a stub for non-Darwin platforms.
|
|
type SecureEnclaveUnlockerMetadata struct {
|
|
UnlockerMetadata
|
|
|
|
SEKeyLabel string `json:"seKeyLabel"`
|
|
SEKeyHash string `json:"seKeyHash"`
|
|
}
|
|
|
|
// SecureEnclaveUnlocker is a stub for non-Darwin platforms.
|
|
type SecureEnclaveUnlocker struct {
|
|
Directory string
|
|
Metadata UnlockerMetadata
|
|
fs afero.Fs
|
|
}
|
|
|
|
// NewSecureEnclaveUnlocker creates a stub SecureEnclaveUnlocker on
|
|
// non-Darwin platforms. The returned instance's methods that require
|
|
// macOS functionality will return errors.
|
|
func NewSecureEnclaveUnlocker(
|
|
fs afero.Fs,
|
|
directory string,
|
|
metadata UnlockerMetadata,
|
|
) *SecureEnclaveUnlocker {
|
|
return &SecureEnclaveUnlocker{
|
|
Directory: directory,
|
|
Metadata: metadata,
|
|
fs: fs,
|
|
}
|
|
}
|
|
|
|
// GetIdentity returns an error on non-Darwin platforms.
|
|
func (s *SecureEnclaveUnlocker) GetIdentity() (*age.X25519Identity, error) {
|
|
return nil, errSENotSupported
|
|
}
|
|
|
|
// GetType returns the unlocker type.
|
|
func (s *SecureEnclaveUnlocker) GetType() string {
|
|
return seUnlockerType
|
|
}
|
|
|
|
// GetMetadata returns the unlocker metadata.
|
|
func (s *SecureEnclaveUnlocker) GetMetadata() UnlockerMetadata {
|
|
return s.Metadata
|
|
}
|
|
|
|
// GetDirectory returns the unlocker directory.
|
|
func (s *SecureEnclaveUnlocker) GetDirectory() string {
|
|
return s.Directory
|
|
}
|
|
|
|
// GetID returns the unlocker ID, the name of the unlocker's directory.
|
|
func (s *SecureEnclaveUnlocker) GetID() string {
|
|
return filepath.Base(s.Directory)
|
|
}
|
|
|
|
// Remove returns an error on non-Darwin platforms.
|
|
func (s *SecureEnclaveUnlocker) Remove() error {
|
|
return errSENotSupported
|
|
}
|
|
|
|
// CreateSecureEnclaveUnlocker returns an error on non-Darwin platforms.
|
|
func CreateSecureEnclaveUnlocker(
|
|
_ afero.Fs,
|
|
_ string,
|
|
_, _ *memguard.LockedBuffer,
|
|
) (*SecureEnclaveUnlocker, error) {
|
|
return nil, errSENotSupported
|
|
}
|