func (gc *gpgv1Client) ResolveRecipients(recipients []string) []string {
	return resolveRecipients(gc, recipients)
}
ResolveRecipients converts PGP keyids to email addresses, if possible
package ocicrypt
import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/pkg/errors"
	"golang.org/x/term"
)
type GPGVersion int
const (
	GPGv2 GPGVersion = iota
	GPGv1
	GPGVersionUndetermined
)
type GPGClient interface {
	ReadGPGPubRingFile() ([]byte, error)
	GetGPGPrivateKey(keyid uint64, passphrase string) ([]byte, error)
	GetSecretKeyDetails(keyid uint64) ([]byte, bool, error)
	GetKeyDetails(keyid uint64) ([]byte, bool, error)
	ResolveRecipients([]string) []string
}
type gpgClient struct {
	gpgHomeDir string
}
type gpgv2Client struct {
	gpgClient
}
type gpgv1Client struct {
	gpgClient
}
func GuessGPGVersion() GPGVersion {
	if err := exec.Command("gpg2", "--version").Run(); err == nil {
		return GPGv2
	} else if err := exec.Command("gpg", "--version").Run(); err == nil {
		return GPGv1
	} else {
		return GPGVersionUndetermined
	}
}
func NewGPGClient(gpgVersion, gpgHomeDir string) (GPGClient, error) {
	v := new(GPGVersion)
	switch gpgVersion {
	case "v1":
		*v = GPGv1
	case "v2":
		*v = GPGv2
	default:
		v = nil
	}
	return newGPGClient(v, gpgHomeDir)
}
func newGPGClient(version *GPGVersion, homedir string) (GPGClient, error) {
	var gpgVersion GPGVersion
	if version != nil {
		gpgVersion = *version
	} else {
		gpgVersion = GuessGPGVersion()
	}
	switch gpgVersion {
	case GPGv1:
		return &gpgv1Client{
			gpgClient: gpgClient{gpgHomeDir: homedir},
		}, nil
	case GPGv2:
		return &gpgv2Client{
			gpgClient: gpgClient{gpgHomeDir: homedir},
		}, nil
	case GPGVersionUndetermined:
		return nil, fmt.Errorf("unable to determine GPG version")
	default:
		return nil, fmt.Errorf("unhandled case: NewGPGClient")
	}
}
func (gc *gpgv2Client) GetGPGPrivateKey(keyid uint64, passphrase string) ([]byte, error) {
	var args []string
	if gc.gpgHomeDir != "" {
		args = append(args, []string{"--homedir", gc.gpgHomeDir}...)
	}
	rfile, wfile, err := os.Pipe()
	if err != nil {
		return nil, errors.Wrapf(err, "could not create pipe")
	}
	defer func() {
		rfile.Close()
		wfile.Close()
	}()
	go func(passphrase string) {
		_, _ = wfile.Write([]byte(passphrase))
		wfile.Close()
	}(passphrase)
	args = append(args, []string{"--pinentry-mode", "loopback", "--batch", "--passphrase-fd", fmt.Sprintf("%d", 3), "--export-secret-key", fmt.Sprintf("0x%x", keyid)}...)
	cmd := exec.Command("gpg2", args...)
	cmd.ExtraFiles = []*os.File{rfile}
	return runGPGGetOutput(cmd)
}
func (gc *gpgv2Client) ReadGPGPubRingFile() ([]byte, error) {
	var args []string
	if gc.gpgHomeDir != "" {
		args = append(args, []string{"--homedir", gc.gpgHomeDir}...)
	}
	args = append(args, []string{"--batch", "--export"}...)
	cmd := exec.Command("gpg2", args...)
	return runGPGGetOutput(cmd)
}
func (gc *gpgv2Client) getKeyDetails(option string, keyid uint64) ([]byte, bool, error) {
	var args []string
	if gc.gpgHomeDir != "" {
		args = []string{"--homedir", gc.gpgHomeDir}
	}
	args = append(args, option, fmt.Sprintf("0x%x", keyid))
	cmd := exec.Command("gpg2", args...)
	keydata, err := runGPGGetOutput(cmd)
	return keydata, err == nil, err
}
func (gc *gpgv2Client) GetSecretKeyDetails(keyid uint64) ([]byte, bool, error) {
	return gc.getKeyDetails("-K", keyid)
}
func (gc *gpgv2Client) GetKeyDetails(keyid uint64) ([]byte, bool, error) {
	return gc.getKeyDetails("-k", keyid)
}
func (gc *gpgv2Client) ResolveRecipients(recipients []string) []string {
	return resolveRecipients(gc, recipients)
}
func (gc *gpgv1Client) GetGPGPrivateKey(keyid uint64, _ string) ([]byte, error) {
	var args []string
	if gc.gpgHomeDir != "" {
		args = append(args, []string{"--homedir", gc.gpgHomeDir}...)
	}
	args = append(args, []string{"--batch", "--export-secret-key", fmt.Sprintf("0x%x", keyid)}...)
	cmd := exec.Command("gpg", args...)
	return runGPGGetOutput(cmd)
}
func (gc *gpgv1Client) ReadGPGPubRingFile() ([]byte, error) {
	var args []string
	if gc.gpgHomeDir != "" {
		args = append(args, []string{"--homedir", gc.gpgHomeDir}...)
	}
	args = append(args, []string{"--batch", "--export"}...)
	cmd := exec.Command("gpg", args...)
	return runGPGGetOutput(cmd)
}
func (gc *gpgv1Client) getKeyDetails(option string, keyid uint64) ([]byte, bool, error) {
	var args []string
	if gc.gpgHomeDir != "" {
		args = []string{"--homedir", gc.gpgHomeDir}
	}
	args = append(args, option, fmt.Sprintf("0x%x", keyid))
	cmd := exec.Command("gpg", args...)
	keydata, err := runGPGGetOutput(cmd)
	return keydata, err == nil, err
}
func (gc *gpgv1Client) GetSecretKeyDetails(keyid uint64) ([]byte, bool, error) {
	return gc.getKeyDetails("-K", keyid)
}
func (gc *gpgv1Client) GetKeyDetails(keyid uint64) ([]byte, bool, error) {
	return gc.getKeyDetails("-k", keyid)
}