Adds pm key export
This commit is contained in:
parent
e18aee5b4f
commit
6f41544659
@ -19,6 +19,7 @@ const keyUsage = `pm keyring: interact with pm's OpenPGP keyring
|
||||
|
||||
subcommands:
|
||||
create (c) -- create a fresh keypair
|
||||
export (e) -- export a public key to stdout
|
||||
list (ls) -- list configured key info
|
||||
`
|
||||
|
||||
@ -40,7 +41,7 @@ func main() {
|
||||
if len(os.Args[1:]) < 2 {
|
||||
fatalf("pm keyring: insufficient args\n\nusage: %v", keyUsage)
|
||||
}
|
||||
sub := os.Args[2]
|
||||
sub, args := os.Args[2], os.Args[3:]
|
||||
switch sub {
|
||||
case "ls", "list":
|
||||
if err := keyring.ListKeys(root, os.Stdout); err != nil {
|
||||
@ -71,6 +72,14 @@ func main() {
|
||||
if err := keyring.NewKeyPair(root, name, email); err != nil {
|
||||
fatalf("creating keypair: %v\n", err)
|
||||
}
|
||||
case "export", "e":
|
||||
if len(args) != 1 {
|
||||
fatalf("missing email argument\n")
|
||||
}
|
||||
email := args[0]
|
||||
if err := keyring.Export(root, os.Stdout, email); err != nil {
|
||||
fatalf("exporting public key for %q: %v\n", email, err)
|
||||
}
|
||||
default:
|
||||
fatalf("unknown keyring subcommand: %q\n\nusage: %v", sub, keyUsage)
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/crypto/openpgp"
|
||||
"golang.org/x/crypto/openpgp/armor"
|
||||
|
||||
"mcquay.me/fs"
|
||||
)
|
||||
@ -102,6 +103,37 @@ func ListKeys(root string, w io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Export prints pubkey information associated with email to w.
|
||||
func Export(root string, w io.Writer, email string) error {
|
||||
if err := ensureDir(root); err != nil {
|
||||
return errors.Wrap(err, "can't find or create pgp dir")
|
||||
}
|
||||
srn, prn := getNames(root)
|
||||
_, pubs, err := getELs(srn, prn)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting existing keyrings")
|
||||
}
|
||||
|
||||
e, err := findKey(pubs, email)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "find key")
|
||||
}
|
||||
|
||||
aw, err := armor.Encode(w, openpgp.PublicKeyType, nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "creating armor encoder")
|
||||
}
|
||||
|
||||
if err := e.Serialize(aw); err != nil {
|
||||
return errors.Wrap(err, "serializing key")
|
||||
}
|
||||
if err := aw.Close(); err != nil {
|
||||
return errors.Wrap(err, "closing armor encoder")
|
||||
}
|
||||
fmt.Fprintf(w, "\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
func pGPDir(root string) string {
|
||||
return filepath.Join(root, "var", "lib", "pm", "pgp")
|
||||
}
|
||||
@ -153,3 +185,30 @@ func getELs(secring, pubring string) (openpgp.EntityList, openpgp.EntityList, er
|
||||
}
|
||||
return sr, pr, nil
|
||||
}
|
||||
|
||||
func findKey(el openpgp.EntityList, id string) (*openpgp.Entity, error) {
|
||||
var e *openpgp.Entity
|
||||
if strings.Contains(id, "@") {
|
||||
es := openpgp.EntityList{}
|
||||
for _, p := range el {
|
||||
for _, v := range p.Identities {
|
||||
if id == v.UserId.Email {
|
||||
es = append(es, p)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(es) == 1 {
|
||||
return es[0], nil
|
||||
}
|
||||
if len(es) > 1 {
|
||||
return nil, errors.New("too many keys matched; try searching by key id?")
|
||||
}
|
||||
} else {
|
||||
for _, p := range el {
|
||||
if id == p.PrimaryKey.KeyIdShortString() {
|
||||
return p, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return e, fmt.Errorf("key %q not found", id)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user