~sircmpwn/aerc

swap out local keyring for system gpg v1 PROPOSED

Mark Wilkerson: 1
 swap out local keyring for system gpg

 7 files changed, 17 insertions(+), 40 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~sircmpwn/aerc/patches/27092/mbox | git am -3
Learn more about email & git

[PATCH] swap out local keyring for system gpg Export this patch

/x/crypto/openpgp has been deprecated by the golang team. Given the
current state of the lib, support for things like smartcards may not be
possible.

See: https://github.com/golang/go/issues/44226
This patch allows for decrypting with existing keyrings and smartcards, but 
doesn't yet populate the fields for signature verification. I haven't been able
to come up with a solution that doesn't involve hacky parsing of the gpg
log output (which is also annoyingly sent to stderr). Parsing this output also
breaks the idea of having user specified pgp commands in the config.

The right way to do this is probably to interface with gpg-agent, but
that's a rabbit hole I don't have the bandwidth to sign up for.

Open to suggestions!
---
 aerc.go                  |  4 ----
 commands/account/view.go |  2 +-
 commands/msg/delete.go   |  2 +-
 commands/msgview/next.go |  2 +-
 lib/messageview.go       | 20 +++++++++++++-------
 widgets/aerc.go          | 25 -------------------------
 widgets/msglist.go       |  2 +-
 7 files changed, 17 insertions(+), 40 deletions(-)

diff --git a/aerc.go b/aerc.go
index b3338ba..dd08619 100644
--- a/aerc.go
+++ b/aerc.go
@@ -187,10 +187,6 @@ func main() {
		ui.EnableMouse()
	}

	logger.Println("Initializing PGP keyring")
	lib.InitKeyring()
	defer lib.UnlockKeyring()

	logger.Println("Starting Unix server")
	as, err := lib.StartServer(logger)
	if err != nil {
diff --git a/commands/account/view.go b/commands/account/view.go
index 4f59d94..48c7bfc 100644
--- a/commands/account/view.go
+++ b/commands/account/view.go
@@ -42,7 +42,7 @@ func (ViewMessage) Execute(aerc *widgets.Aerc, args []string) error {
		aerc.PushError(msg.Error.Error())
		return nil
	}
	lib.NewMessageStoreView(msg, store, aerc.DecryptKeys,
	lib.NewMessageStoreView(msg, store,
		func(view lib.MessageView, err error) {
			if err != nil {
				aerc.PushError(err.Error())
diff --git a/commands/msg/delete.go b/commands/msg/delete.go
index 34eac72..e9dbd93 100644
--- a/commands/msg/delete.go
+++ b/commands/msg/delete.go
@@ -68,7 +68,7 @@ func (Delete) Execute(aerc *widgets.Aerc, args []string) error {
				acct.Messages().Invalidate()
				return nil
			}
			lib.NewMessageStoreView(next, store, aerc.DecryptKeys,
			lib.NewMessageStoreView(next, store,
				func(view lib.MessageView, err error) {
					if err != nil {
						aerc.PushError(err.Error())
diff --git a/commands/msgview/next.go b/commands/msgview/next.go
index 4291a6a..d61300e 100644
--- a/commands/msgview/next.go
+++ b/commands/msgview/next.go
@@ -37,7 +37,7 @@ func (NextPrevMsg) Execute(aerc *widgets.Aerc, args []string) error {
		aerc.RemoveTab(mv)
		return nil
	}
	lib.NewMessageStoreView(nextMsg, store, aerc.DecryptKeys,
	lib.NewMessageStoreView(nextMsg, store,
		func(view lib.MessageView, err error) {
			if err != nil {
				aerc.PushError(err.Error())
diff --git a/lib/messageview.go b/lib/messageview.go
index 532d2c8..740ce3a 100644
--- a/lib/messageview.go
+++ b/lib/messageview.go
@@ -4,10 +4,10 @@ import (
	"bytes"
	"io"
	"io/ioutil"
	"os/exec"

	"github.com/emersion/go-message"
	_ "github.com/emersion/go-message/charset"
	"github.com/emersion/go-pgpmail"
	"golang.org/x/crypto/openpgp"

	"git.sr.ht/~rjarry/aerc/models"
@@ -30,6 +30,7 @@ type MessageView interface {
	// Fetches a specific body part for this message
	FetchBodyPart(part []int, cb func(io.Reader))

	// TODO figure out what parts we actually need
	PGPDetails() *openpgp.MessageDetails
}

@@ -56,13 +57,12 @@ type MessageStoreView struct {
	messageInfo   *models.MessageInfo
	messageStore  *MessageStore
	message       []byte
	details       *openpgp.MessageDetails
	details       *openpgp.MessageDetails // TODO
	bodyStructure *models.BodyStructure
}

func NewMessageStoreView(messageInfo *models.MessageInfo,
	store *MessageStore, decryptKeys openpgp.PromptFunction,
	cb func(MessageView, error)) {
	store *MessageStore, cb func(MessageView, error)) {

	msv := &MessageStoreView{messageInfo, store,
		nil, nil, messageInfo.BodyStructure}
@@ -70,12 +70,18 @@ func NewMessageStoreView(messageInfo *models.MessageInfo,
	if usePGP(messageInfo.BodyStructure) {
		store.FetchFull([]uint32{messageInfo.Uid}, func(fm *types.FullMessage) {
			reader := fm.Content.Reader
			pgpReader, err := pgpmail.Read(reader, Keyring, decryptKeys, nil)
			cmd := exec.Command("gpg", "-d")
			cmd.Stdin = reader
			out, err := cmd.StdoutPipe()

			if err != nil {
				cb(nil, err)
				return
			}
			msv.message, err = ioutil.ReadAll(pgpReader.MessageDetails.UnverifiedBody)
			// TODO should handle this error
			go cmd.Run()

			msv.message, err = ioutil.ReadAll(out)
			if err != nil {
				cb(nil, err)
				return
@@ -91,7 +97,7 @@ func NewMessageStoreView(messageInfo *models.MessageInfo,
				return
			}
			msv.bodyStructure = bs
			msv.details = pgpReader.MessageDetails
			msv.details = &openpgp.MessageDetails{}
			cb(msv, nil)
		})
	} else {
diff --git a/widgets/aerc.go b/widgets/aerc.go
index cbde56c..5fcf922 100644
--- a/widgets/aerc.go
+++ b/widgets/aerc.go
@@ -12,7 +12,6 @@ import (
	"github.com/emersion/go-message/mail"
	"github.com/gdamore/tcell/v2"
	"github.com/google/shlex"
	"golang.org/x/crypto/openpgp"

	"git.sr.ht/~rjarry/aerc/config"
	"git.sr.ht/~rjarry/aerc/lib"
@@ -613,30 +612,6 @@ func (aerc *Aerc) Initialize(ui *ui.UI) {
	aerc.ui = ui
}

func (aerc *Aerc) DecryptKeys(keys []openpgp.Key, symmetric bool) (b []byte, err error) {
	for _, key := range keys {
		ident := key.Entity.PrimaryIdentity()
		chPass, chErr := aerc.GetPassword("Decrypt PGP private key",
			fmt.Sprintf("Enter password for %s (%8X)\nPress <ESC> to cancel",
				ident.Name, key.PublicKey.KeyId))

		for {
			select {
			case err = <-chErr:
				if err != nil {
					return nil, err
				}
				pass := <-chPass
				err = key.PrivateKey.Decrypt([]byte(pass))
				return nil, err
			default:
				aerc.ui.Tick()
			}
		}
	}
	return nil, err
}

// errorScreen is a widget that draws an error in the middle of the context
func errorScreen(s string, conf config.UIConfig) ui.Drawable {
	errstyle := conf.GetStyle(config.STYLE_ERROR)
diff --git a/widgets/msglist.go b/widgets/msglist.go
index 6163d0e..07c0bfa 100644
--- a/widgets/msglist.go
+++ b/widgets/msglist.go
@@ -296,7 +296,7 @@ func (ml *MessageList) MouseEvent(localX int, localY int, event tcell.Event) {
				if msg == nil {
					return
				}
				lib.NewMessageStoreView(msg, store, ml.aerc.DecryptKeys,
				lib.NewMessageStoreView(msg, store,
					func(view lib.MessageView, err error) {
						if err != nil {
							ml.aerc.PushError(err.Error())
-- 
2.34.0
Hi Mark,

The project has been forked a while ago. In the future, could you please
send patches to the new mailing list as well?

  ~rjarry/aerc-devel@lists.sr.ht

Mark Wilkerson, Dec 04, 2021 at 04:57: