EPA in Emacs is a Neat UX on top of GPG

Posted on June 7, 2022 by Richard Goulter
Tags: ,

GPG is notorious for having an archane interface which is easy to misuse.

As a developer, the most I’ve used it for has been to sign git commits.

Emacs supports a workflow which uses GPG to automatically decrypt the file when reading it, and automatically encrypt the file when saving it.

With the Doom Emacs distribution of Emacs, if the user’s config.el sets user-full-name or user-mail-address, and the GnuPG keyring on the computer has a PGP key pair with this as a user ID, then this works seamlessly. (Well, subject to things like pinentry and GPG agents and all).

Even that sounds complicated; but you probably will have those things set if you’re using Doom Emacs; and probably do have GPG keys with your email/name if you’ve used GPG for anything.

Since the acronyms are confusing:

Some notes:

Doom Emacs achieves this in its modules/config/default/config.el:

(after! epa
  ;; With GPG 2.1+, this forces gpg-agent to use the Emacs minibuffer to prompt
  ;; for the key passphrase.
  (set 'epg-pinentry-mode 'loopback)
  ;; Default to the first enabled and non-expired key in your keyring.
  (setq-default
   epa-file-encrypt-to
   (or (default-value 'epa-file-encrypt-to)
       (unless (string-empty-p user-full-name)
         (when-let (context (ignore-errors (epg-make-context)))
           (cl-loop for key in (epg-list-keys context user-full-name 'public)
                    for subkey = (car (epg-key-sub-key-list key))
                    if (not (memq 'disabled (epg-sub-key-capability subkey)))
                    if (< (or (epg-sub-key-expiration-time subkey) 0)
                          (time-to-seconds))
                    collect (epg-sub-key-fingerprint subkey))))
       user-mail-address))
   ;; And suppress prompts if epa-file-encrypt-to has a default value (without
   ;; overwriting file-local values).
  (defadvice! +default--dont-prompt-for-keys-a (&rest _)
    :before #'epa-file-write-region
    (unless (local-variable-p 'epa-file-encrypt-to)
      (setq-local epa-file-encrypt-to (default-value 'epa-file-encrypt-to)))))

Since it wasn’t obvious to me: the epa-file-encrypt-to is used to determine which PGP keys in the keyring to encrypt the file to.
It’s sortof similar to the --recipient flag when using gpg --encrypt. Some additional functionality EPA adds is that if there are multiple public keys which match, EPA will encrypt the file for all of these; whereas gpg --encrypt will only encrypt for the most recent encryption key which matches.

When opening an encrypted file, epa-file-encrypt-to will be filled with the keys which were used to encrypt the file. You can change the value of this variable to change which keys are used to encrypt the file.

Also, since it wasn’t obvious to me: a file encrypted with gpg for multiple keys is like a concatenation of the file encrypted for each key. So a file can obviously be encrypted for multiple keys; and that encrypted file can be decrypted with any of the keys it was encrypted with.

In Emacs, you can visit the info node for EPA’s encrypting/decrypting by executing the elisp:

(info "(epa) Encrypting/decrypting gpg files")

(assuming epa.info has been installed to the right place).

Or, going to the “EasyPG Assistant” manual, “Commands”, “Encrypting/decrypting gpg files” menu items.

Or, in the online manual: https://www.gnu.org/software/emacs/manual/html_node/epa/Encrypting_002fdecrypting-gpg-files.html.


Newer post Older post