github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/client/cmd_pgp_export.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package client
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  	"strings"
    10  
    11  	"golang.org/x/net/context"
    12  
    13  	"github.com/keybase/cli"
    14  	"github.com/keybase/client/go/libcmdline"
    15  	"github.com/keybase/client/go/libkb"
    16  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    17  	"github.com/keybase/go-framed-msgpack-rpc/rpc"
    18  )
    19  
    20  func NewCmdPGPExport(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
    21  	return cli.Command{
    22  		Name:  "export",
    23  		Usage: "Export a PGP key from keybase",
    24  		Action: func(c *cli.Context) {
    25  			cl.ChooseCommand(&CmdPGPExport{Contextified: libkb.NewContextified(g)}, "export", c)
    26  		},
    27  		Flags: []cli.Flag{
    28  			cli.StringFlag{
    29  				Name:  "o, outfile",
    30  				Usage: "Specify an outfile (stdout by default).",
    31  			},
    32  			cli.BoolFlag{
    33  				Name:  "s, secret",
    34  				Usage: "Export secret key.",
    35  			},
    36  			cli.StringFlag{
    37  				Name:  "q, query",
    38  				Usage: "Only export keys matching that query.",
    39  			},
    40  			cli.BoolFlag{
    41  				Name:  "unencrypted",
    42  				Usage: "When exporting private keys, do not protect with a passphrase.",
    43  			},
    44  		},
    45  		Description: `"keybase pgp export" exports public (and optionally private)
    46     PGP keys from Keybase, and into a file or to standard output.
    47     It doesn't access the GnuPG keychain at all. By default, when
    48     exporting private keys, you will be asked for passphrase to encrypt
    49     the exported keys.`,
    50  	}
    51  }
    52  
    53  type CmdPGPExport struct {
    54  	UnixFilter
    55  	arg     keybase1.PGPExportArg
    56  	outfile string
    57  	libkb.Contextified
    58  }
    59  
    60  func (s *CmdPGPExport) ParseArgv(ctx *cli.Context) error {
    61  	nargs := len(ctx.Args())
    62  	var err error
    63  
    64  	s.arg.Options.Secret = ctx.Bool("secret")
    65  	s.arg.Options.Query = ctx.String("query")
    66  	s.arg.Encrypted = !ctx.Bool("unencrypted")
    67  	s.outfile = ctx.String("outfile")
    68  
    69  	if nargs > 0 {
    70  		err = fmt.Errorf("export doesn't take args")
    71  	}
    72  
    73  	return err
    74  }
    75  
    76  func (s *CmdPGPExport) Run() (err error) {
    77  	protocols := []rpc.Protocol{
    78  		NewSecretUIProtocol(s.G()),
    79  	}
    80  
    81  	cli, err := GetPGPClient(s.G())
    82  	if err != nil {
    83  		return err
    84  	}
    85  	if err = RegisterProtocolsWithContext(protocols, s.G()); err != nil {
    86  		return err
    87  	}
    88  	return s.finish(cli.PGPExport(context.TODO(), s.arg))
    89  }
    90  
    91  func (s *CmdPGPExport) finish(res []keybase1.KeyInfo, inErr error) error {
    92  	if inErr != nil {
    93  		return inErr
    94  	}
    95  	if len(res) > 1 {
    96  		s.G().Log.Warning("Found several matches:")
    97  		for _, k := range res {
    98  			// XXX os.Stderr?  why not Log?
    99  			os.Stderr.Write([]byte(k.Desc + "\n\n"))
   100  		}
   101  		return fmt.Errorf("Specify a key to export")
   102  	}
   103  	if len(res) == 0 {
   104  		return fmt.Errorf("No matching keys found")
   105  	}
   106  
   107  	snk := initSink(s.G(), s.outfile)
   108  	if err := snk.Open(); err != nil {
   109  		return err
   110  	}
   111  	_, err := snk.Write([]byte(strings.TrimSpace(res[0].Key)))
   112  	if err != nil {
   113  		return err
   114  	}
   115  	_, err = snk.Write([]byte{'\n'})
   116  	if err != nil {
   117  		return err
   118  	}
   119  	return snk.Close()
   120  }
   121  
   122  func (s *CmdPGPExport) GetUsage() libkb.Usage {
   123  	return libkb.Usage{
   124  		Config:    true,
   125  		API:       true,
   126  		KbKeyring: true,
   127  	}
   128  }