summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTim Culverhouse <tim@timculverhouse.com>2022-05-05 12:53:16 -0500
committerRobin Jarry <robin@jarry.cc>2022-05-06 11:02:55 +0200
commitb57fceaad4bfcbd4ca3022e013b73eff72079c0b (patch)
tree7e68b206ca5b5dd7d1e2a8793360a80963c0c1df /lib
parent32a16dcd8dc488c1f360553d9d9f6d121af1b367 (diff)
downloadaerc-b57fceaad4bfcbd4ca3022e013b73eff72079c0b.zip
pgp: add attach key command
Add compose command ("attach-key") to attach the public key associated with the sending account. Public key is attached in ascii armor format, with the mimetype set according to RFC 3156 ("application/pgp-keys"). Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Tested-by: Koni Marti <koni.marti@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/crypto/crypto.go1
-rw-r--r--lib/crypto/gpg/gpg.go4
-rw-r--r--lib/crypto/gpg/gpgbin/keys.go23
-rw-r--r--lib/crypto/pgp/pgp.go34
4 files changed, 61 insertions, 1 deletions
diff --git a/lib/crypto/crypto.go b/lib/crypto/crypto.go
index 54a20e6..3c961ad 100644
--- a/lib/crypto/crypto.go
+++ b/lib/crypto/crypto.go
@@ -21,6 +21,7 @@ type Provider interface {
Close()
GetSignerKeyId(string) (string, error)
GetKeyId(string) (string, error)
+ ExportKey(string) (io.Reader, error)
}
func New(s string) Provider {
diff --git a/lib/crypto/gpg/gpg.go b/lib/crypto/gpg/gpg.go
index fe32468..00125ba 100644
--- a/lib/crypto/gpg/gpg.go
+++ b/lib/crypto/gpg/gpg.go
@@ -59,6 +59,10 @@ func (m *Mail) GetKeyId(s string) (string, error) {
return gpgbin.GetKeyId(s)
}
+func (m *Mail) ExportKey(k string) (io.Reader, error) {
+ return gpgbin.ExportPublicKey(k)
+}
+
func handleSignatureError(e string) models.SignatureValidity {
if e == "gpg: missing public key" {
return models.UnknownEntity
diff --git a/lib/crypto/gpg/gpgbin/keys.go b/lib/crypto/gpg/gpgbin/keys.go
index 9c8b233..bef90cf 100644
--- a/lib/crypto/gpg/gpgbin/keys.go
+++ b/lib/crypto/gpg/gpgbin/keys.go
@@ -1,6 +1,12 @@
package gpgbin
-import "fmt"
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "os/exec"
+ "strings"
+)
// GetPrivateKeyId runs gpg --list-secret-keys s
func GetPrivateKeyId(s string) (string, error) {
@@ -21,3 +27,18 @@ func GetKeyId(s string) (string, error) {
}
return id, nil
}
+
+// ExportPublicKey exports the public key identified by k in armor format
+func ExportPublicKey(k string) (io.Reader, error) {
+ cmd := exec.Command("gpg", "--export", "--armor", k)
+
+ var outbuf bytes.Buffer
+ var stderr strings.Builder
+ cmd.Stdout = &outbuf
+ cmd.Stderr = &stderr
+ cmd.Run()
+ if strings.Contains(stderr.String(), "gpg") {
+ return nil, fmt.Errorf("gpg: error exporting key")
+ }
+ return &outbuf, nil
+}
diff --git a/lib/crypto/pgp/pgp.go b/lib/crypto/pgp/pgp.go
index f0f3f65..4dbe37c 100644
--- a/lib/crypto/pgp/pgp.go
+++ b/lib/crypto/pgp/pgp.go
@@ -13,6 +13,7 @@ import (
"git.sr.ht/~rjarry/aerc/models"
"github.com/ProtonMail/go-crypto/openpgp"
+ "github.com/ProtonMail/go-crypto/openpgp/armor"
"github.com/ProtonMail/go-crypto/openpgp/packet"
"github.com/emersion/go-message/mail"
"github.com/emersion/go-pgpmail"
@@ -271,6 +272,39 @@ func (m *Mail) GetKeyId(s string) (string, error) {
return entity.PrimaryKey.KeyIdString(), nil
}
+func (m *Mail) ExportKey(k string) (io.Reader, error) {
+ var err error
+ var entity *openpgp.Entity
+ switch strings.Contains(k, "@") {
+ case true:
+ entity, err = m.getSignerEntityByEmail(k)
+ if err != nil {
+ return nil, err
+ }
+ case false:
+ entity, err = m.getSignerEntityByKeyId(k)
+ if err != nil {
+ return nil, err
+ }
+ }
+ pks := bytes.NewBuffer(nil)
+ err = entity.Serialize(pks)
+ if err != nil {
+ return nil, fmt.Errorf("pgp: error exporting key: %v", err)
+ }
+ pka := bytes.NewBuffer(nil)
+ w, err := armor.Encode(pka, "PGP PUBLIC KEY BLOCK", map[string]string{})
+ if err != nil {
+ return nil, fmt.Errorf("pgp: error exporting key: %v", err)
+ }
+ w.Write(pks.Bytes())
+ if err != nil {
+ return nil, fmt.Errorf("pgp: error exporting key: %v", err)
+ }
+ w.Close()
+ return pka, nil
+}
+
func handleSignatureError(e string) models.SignatureValidity {
if e == "openpgp: signature made by unknown entity" {
return models.UnknownEntity