func ReadExportedData(params ExportImportCommonParams) ([]byte, error) {
	dataFile := params.ExportDataFile()
	exportedKeyData, err := ioutil.ReadFile(dataFile)
	if err != nil {
		log.WithField("path", dataFile).WithError(err).Debug("Failed to read data file")
		return nil, err
	}
	return exportedKeyData, nil
}
ReadExportedData reads exported key data from designated file.
package keys
import (
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"github.com/cossacklabs/acra/cmd"
	"github.com/cossacklabs/acra/keystore"
	keystoreV2 "github.com/cossacklabs/acra/keystore/v2/keystore"
	"github.com/cossacklabs/acra/keystore/v2/keystore/api"
	"github.com/cossacklabs/acra/keystore/v2/keystore/crypto"
	"github.com/cossacklabs/acra/utils"
	log "github.com/sirupsen/logrus"
)
const ExportKeyPerm = os.FileMode(0600)
var (
	ErrIncorrectPerm = errors.New("incorrect output file permissions")
)
type ExportImportCommonParams interface {
	ExportKeysFile() string
	ExportDataFile() string
}
type CommonExportImportParameters struct {
	exportKeysFile string
	exportDataFile string
}
func (p *CommonExportImportParameters) ExportKeysFile() string {
	return p.exportKeysFile
}
func (p *CommonExportImportParameters) ExportDataFile() string {
	return p.exportDataFile
}
func (p *CommonExportImportParameters) Register(flags *flag.FlagSet, filePurspose string) {
	flags.StringVar(&p.exportDataFile, "key_bundle_file", "", "path to "+filePurspose+" file for exported key bundle")
	flags.StringVar(&p.exportKeysFile, "key_bundle_secret", "", "path to "+filePurspose+" file for key encryption keys")
}
func (p *CommonExportImportParameters) validate() error {
	if p.exportDataFile == "" || p.exportKeysFile == "" {
		log.Errorf("\"--key_bundle_file\" and \"--key_bundle_secret\" options are required")
		return ErrMissingOutputFile
	}
	if p.exportDataFile == p.exportKeysFile {
		log.Errorf("\"--key_bundle_file\" and \"--key_bundle_secret\" must not be the same file")
		return ErrOutputSame
	}
	return nil
}
type ExportKeysParams interface {
	ExportImportCommonParams
	ExportIDs() []string
	ExportAll() bool
	ExportPrivate() bool
}
type ExportKeysSubcommand struct {
	CommonKeyStoreParameters
	CommonExportImportParameters
	FlagSet *flag.FlagSet
	exportIDs     []string
	exportAll     bool
	exportPrivate bool
}
func (p *ExportKeysSubcommand) Name() string {
	return CmdExportKeys
}
func (p *ExportKeysSubcommand) GetFlagSet() *flag.FlagSet {
	return p.FlagSet
}
func (p *ExportKeysSubcommand) RegisterFlags() {
	p.FlagSet = flag.NewFlagSet(CmdExportKeys, flag.ContinueOnError)
	p.CommonKeyStoreParameters.Register(p.FlagSet)
	p.CommonExportImportParameters.Register(p.FlagSet, "output")
	p.FlagSet.BoolVar(&p.exportAll, "all", false, "export all keys")
	p.FlagSet.BoolVar(&p.exportPrivate, "private_keys", false, "export private key data")
	p.FlagSet.Usage = func() {
		fmt.Fprintf(os.Stderr, "Command \"%s\": export keys from the keystore\n", CmdExportKeys)
		fmt.Fprintf(os.Stderr, "\n\t%s %s [options...] --key_bundle_file <file> --key_bundle_secret <file> <key-ID...>\n", os.Args[0], CmdExportKeys)
		fmt.Fprintf(os.Stderr, "\nOptions:\n")
		cmd.PrintFlags(p.FlagSet)
	}
}
func (p *ExportKeysSubcommand) Parse(arguments []string) error {
	err := cmd.ParseFlagsWithConfig(p.FlagSet, arguments, DefaultConfigPath, ServiceName)
	if err != nil {
		return err
	}
	err = p.CommonExportImportParameters.validate()
	if err != nil {
		return err
	}
	args := p.FlagSet.Args()
	if len(args) < 1 && !p.exportAll {
		log.Errorf("\"%s\" command requires at least one key ID", CmdExportKeys)
		log.Infoln("Use \"--all\" to export all keys")
		return ErrMissingKeyID
	}
	p.exportIDs = args
	return nil
}
func (p *ExportKeysSubcommand) Execute() {
	keyStore, err := OpenKeyStoreForExport(p)
	if err != nil {
		if err == ErrNotImplementedV1 {
			warnKeystoreV2Only(CmdExportKeys)
		}
		log.WithError(err).Fatal("Failed to open keystore")
	}
	ExportKeysCommand(p, keyStore)
}
func (p *ExportKeysSubcommand) ExportIDs() []string {
	return p.exportIDs
}
func (p *ExportKeysSubcommand) ExportAll() bool {
	return p.exportAll
}
func (p *ExportKeysSubcommand) ExportPrivate() bool {
	return p.exportPrivate
}
type ImportKeysParams interface {
	ExportImportCommonParams
	ListKeysParams
}
type ImportKeysSubcommand struct {
	CommonKeyStoreParameters
	CommonExportImportParameters
	CommonKeyListingParameters
	FlagSet *flag.FlagSet
}
func (p *ImportKeysSubcommand) Name() string {
	return CmdImportKeys
}
func (p *ImportKeysSubcommand) GetFlagSet() *flag.FlagSet {
	return p.FlagSet
}
func (p *ImportKeysSubcommand) RegisterFlags() {
	p.FlagSet = flag.NewFlagSet(CmdImportKeys, flag.ContinueOnError)
	p.CommonKeyStoreParameters.Register(p.FlagSet)
	p.CommonExportImportParameters.Register(p.FlagSet, "input")
	p.CommonKeyListingParameters.Register(p.FlagSet)
	p.FlagSet.Usage = func() {
		fmt.Fprintf(os.Stderr, "Command \"%s\": import keys into the keystore\n", CmdImportKeys)
		fmt.Fprintf(os.Stderr, "\n\t%s %s [options...] --key_bundle_file <file> --key_bundle_secret <file>\n", os.Args[0], CmdImportKeys)
		fmt.Fprintf(os.Stderr, "\nOptions:\n")
		cmd.PrintFlags(p.FlagSet)
	}
}
func (p *ImportKeysSubcommand) Parse(arguments []string) error {
	err := cmd.ParseFlagsWithConfig(p.FlagSet, arguments, DefaultConfigPath, ServiceName)
	if err != nil {
		return err
	}
	err = p.CommonExportImportParameters.validate()
	if err != nil {
		return err
	}
	return nil
}
func (p *ImportKeysSubcommand) Execute() {
	keyStore, err := OpenKeyStoreForImport(p)
	if err != nil {
		if err == ErrNotImplementedV1 {
			warnKeystoreV2Only(CmdExportKeys)
		}
		log.WithError(err).Fatal("Failed to open keystore")
	}
	ImportKeysCommand(p, keyStore)
}
func PrepareExportEncryptionKeys() ([]byte, *crypto.KeyStoreSuite, error) {
	keys, err := keystoreV2.NewMasterKeys()
	if err != nil {
		log.WithError(err).Debug("Failed to generate master keys")
		return nil, nil, err
	}
	serializedKeys, err := keys.Marshal()
	if err != nil {
		log.WithError(err).Debug("Failed to serialize keys in JSON")
		return nil, nil, err
	}
	cryptosuite, err := crypto.NewSCellSuite(keys.Encryption, keys.Signature)
	if err != nil {
		log.WithError(err).Debug("Failed to setup cryptosuite")
		return nil, nil, err
	}
	return serializedKeys, cryptosuite, nil
}
func ReadImportEncryptionKeys(params ExportImportCommonParams) (*crypto.KeyStoreSuite, error) {
	keysFile := params.ExportKeysFile()
	importEncryptionKeyData, err := ioutil.ReadFile(keysFile)
	if err != nil {
		log.WithField("path", keysFile).WithError(err).Debug("Failed to read key file")
		return nil, err
	}
	defer utils.ZeroizeSymmetricKey(importEncryptionKeyData)
	importEncryptionKeys := &keystoreV2.SerializedKeys{}
	err = importEncryptionKeys.Unmarshal(importEncryptionKeyData)
	if err != nil {
		log.WithField("path", keysFile).WithError(err).Debug("Failed to parse key file content")
		return nil, err
	}
	cryptosuite, err := crypto.NewSCellSuite(importEncryptionKeys.Encryption, importEncryptionKeys.Signature)
	if err != nil {
		log.WithField("path", keysFile).WithError(err).Debug("Failed to initialize cryptosuite")
		return nil, err
	}
	return cryptosuite, nil
}
func ExportKeys(keyStore api.KeyStore, cryptosuite *crypto.KeyStoreSuite, params ExportKeysParams) (exportedData []byte, err error) {
	exportedIDs := params.ExportIDs()
	if params.ExportAll() {
		exportedIDs, err = keyStore.ListKeyRings()
		if err != nil {
			log.WithError(err).Debug("Failed to list available keys")
			return nil, err
		}
	}
	mode := api.ExportPublicOnly
	if params.ExportPrivate() {
		mode = api.ExportPrivateKeys
	}
	exportedData, err = keyStore.ExportKeyRings(exportedIDs, cryptosuite, mode)
	if err != nil {
		log.WithError(err).Debug("Failed to export key rings")
		return nil, err
	}
	return exportedData, nil
}
func ImportKeys(exportedData []byte, keyStore api.MutableKeyStore, cryptosuite *crypto.KeyStoreSuite, params ImportKeysParams) ([]keystore.KeyDescription, error) {
	keyIDs, err := keyStore.ImportKeyRings(exportedData, cryptosuite, nil)
	if err != nil {
		log.WithError(err).Debug("Failed to import key rings")
		return nil, err
	}
	descriptions, err := keystoreV2.DescribeKeyRings(keyIDs, keyStore)
	if err != nil {
		log.WithError(err).Debug("Failed to describe imported key rings")
		return nil, err
	}
	return descriptions, nil
}
func WriteExportedData(data, keys []byte, params ExportKeysParams) error {
	err := writeFileWithMode(data, params.ExportDataFile(), ExportKeyPerm)
	if err != nil {
		return err
	}
	err = writeFileWithMode(keys, params.ExportKeysFile(), ExportKeyPerm)
	if err != nil {
		return err
	}
	return nil
}