mirror of
https://github.com/gopasspw/gopass.git
synced 2025-12-08 19:24:54 +00:00
* fix(gpg): Opportunistic key comparison on import When importing keys gopass was already checking if the key was already present. However, GPG is very flexible in which kind of key IDs it accepts. So it could happen that gopass would ask to import a key that is already present in the keyring, but referenced by a different ID. This change makes the check more robust by checking the key's fingerprint before asking for import. If a key with the same fingerprint is already present, the import is skipped. * fix(gpg): Opportunistic key comparison on import When importing keys gopass was already checking if the key was already present. However, GPG is very flexible in which kind of key IDs it accepts. So it could happen that gopass would ask to import a key that is already present in the keyring, but referenced by a different ID. This change makes the check more robust by checking the key's fingerprint before asking for import. If a key with the same fingerprint is already present, the import is skipped. --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
95 lines
2.6 KiB
Go
95 lines
2.6 KiB
Go
package backend
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/blang/semver/v4"
|
|
"github.com/gopasspw/gopass/pkg/debug"
|
|
)
|
|
|
|
// CryptoBackend is a cryptographic backend.
|
|
type CryptoBackend int
|
|
|
|
const (
|
|
// Plain is a no-op crypto backend.
|
|
Plain CryptoBackend = iota
|
|
// GPGCLI is a gpg-cli based crypto backend.
|
|
GPGCLI
|
|
// Age - age-encryption.org.
|
|
Age
|
|
)
|
|
|
|
func (c CryptoBackend) String() string {
|
|
if be, err := CryptoRegistry.BackendName(c); err == nil {
|
|
return be
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// Keyring is a public/private key manager.
|
|
type Keyring interface {
|
|
ListRecipients(ctx context.Context) ([]string, error)
|
|
ListIdentities(ctx context.Context) ([]string, error)
|
|
|
|
FindRecipients(ctx context.Context, needles ...string) ([]string, error)
|
|
FindIdentities(ctx context.Context, needles ...string) ([]string, error)
|
|
|
|
Fingerprint(ctx context.Context, id string) string
|
|
FormatKey(ctx context.Context, id, tpl string) string
|
|
ReadNamesFromKey(ctx context.Context, buf []byte) ([]string, error)
|
|
GetFingerprint(ctx context.Context, key []byte) (string, error)
|
|
|
|
GenerateIdentity(ctx context.Context, name, email, passphrase string) (string, error)
|
|
}
|
|
|
|
// Crypto is a crypto backend.
|
|
type Crypto interface {
|
|
Keyring
|
|
|
|
Encrypt(ctx context.Context, plaintext []byte, recipients []string) ([]byte, error)
|
|
Decrypt(ctx context.Context, ciphertext []byte) ([]byte, error)
|
|
RecipientIDs(ctx context.Context, ciphertext []byte) ([]string, error)
|
|
|
|
Name() string
|
|
Version(context.Context) semver.Version
|
|
Initialized(ctx context.Context) error
|
|
Ext() string // filename extension.
|
|
IDFile() string // recipient IDs.
|
|
Concurrency() int
|
|
}
|
|
|
|
// NewCrypto instantiates a new crypto backend.
|
|
func NewCrypto(ctx context.Context, id CryptoBackend) (Crypto, error) {
|
|
if be, err := CryptoRegistry.Get(id); err == nil {
|
|
return be.New(ctx)
|
|
}
|
|
|
|
return nil, fmt.Errorf("unknown backend %d: %w", id, ErrNotFound)
|
|
}
|
|
|
|
// DetectCrypto tries to detect the crypto backend used.
|
|
func DetectCrypto(ctx context.Context, storage Storage) (Crypto, error) {
|
|
if HasCryptoBackend(ctx) {
|
|
if be, err := CryptoRegistry.Get(GetCryptoBackend(ctx)); err == nil {
|
|
return be.New(ctx)
|
|
}
|
|
}
|
|
|
|
for _, be := range CryptoRegistry.Prioritized() {
|
|
debug.Log("Trying %s for %s", be, storage)
|
|
if err := be.Handles(ctx, storage); err != nil {
|
|
debug.Log("failed to use crypto %s for %s", be, storage)
|
|
|
|
continue
|
|
}
|
|
debug.Log("Using %s for %s", be, storage)
|
|
|
|
return be.New(ctx)
|
|
}
|
|
debug.Log("No valid crypto provider found for %s", storage)
|
|
// TODO: this should return ErrNotSupported, but need to fix some tests for that
|
|
return nil, nil //nolint:nilnil
|
|
}
|