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. PGP unlocker IDs were `pgp-<fingerprint>`; the check that refuses a second PGP unlocker for one key now compares the fingerprint in the other unlockers' 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
|
|
}
|