akuszyk.com

A blog about software engineering, collaboration, and--occasionally--Emacs.

View on GitHub

Editing encrypted files in Emacs

I routinely store note files (normally using org-mode) in Git repos, which I commit automatically using git-auto-commit-mode.

This works really well, but sometimes I’m working on some notes that I want to be ultra-safe in the event that my Git repo is maliciously accessed. On these occasions, I make use of Emacs’ transparent support for editing GPG-encrypted files. Emacs does a fine job of transparently decrypting files when I open them, and encrypting them when I save them. However, I need to make sure that the encryption keys I use for the files are portable across machines, otherwise I might end up with files I can never open again! 😅

In this post, I briefly describe how I make keys portable, as well as how I use Emacs to edit encrypted files.

Generating, exporting, and importing a GPG key

Before using a key to encrypt your notes, you need to generate a key, and make sure you can use it between machines.

Step 1: generating a new key-pair

First of all, generate a new key with:

gpg --full-generate-key

Once you’ve generated a key, you should be able to see it with:

gpg --list-keys

You should see some output like this:

pub   ed25519 2024-01-01 [SC]
      3453298457893DFHJKEHFGKJHFGKJSEH34Y78365
uid           [ultimate] James Kirk (Self-destruct key) <[email protected]>
sub   cv25519 2024-01-01 [E]

Make a note of the key’s ID, which is 3453298457893DFHJKEHFGKJHFGKJSEH34Y78365 in this example.

Step 2: exporting the keys

Now, you can export it as plain-text with:

gpg --armor --export-key 3453298457893DFHJKEHFGKJHFGKJSEH34Y78365 > public.key
gpg --armor --export-secret-key 3453298457893DFHJKEHFGKJHFGKJSEH34Y78365 > private.key

Keep these files safe, and take care transmitting them to your other machines! I store them in a password manager.

Step 3: importing they keys elsewhere

These keys can be imported with:

gpg --import public.key
gpg --import private.key

And, finally, your imported key can be trusted with:

gpg --edit-key 3453298457893DFHJKEHFGKJHFGKJSEH34Y78365 trust quit

At the menu, choose option 5: ultimate trust.

Now you’re all set with an encryption key you can distribute between your machines! 🔒

💡 A note on asymmetric, versus symmetric encryption

GPG supports symmetric encryption with a passphrase, as well as asymmetric encryption (which is what the key set-up above is for). Using symmetric encryption across different machines is easy; all you need is the passphrase, and you can decrypt your files anywhere. For symmetric encryption, you don’t need to create keys, or distribute them across machines.

However, whilst this makes the set-up easier, it is less ergonomic on a day-to-day basis. The passphrase for symmetric encryption is required to encrypt and decrypt the file, and (in my experience) GPG agent prompts for this passphrase regularly (e.g. every write to the file). On the other hand, with asymmetric encryption, the file can be encrypted using the public key (which requires no passphrase), and the GPG agent does a good job of caching the passphrase for the private key.

So, although it’s more effort to set-up asymmetric encryption, I prefer it for everyday encryption of files, because it limits the number of times I need to enter my passphrase.

Configuring Emacs to work well with encrypted files

If you want to automatically encrypt files with a *.gpg extension when you save them, you might also find these Emacs settings useful.

First, allow passphrases to be entered directly in Emacs from the minibuffer:

(setq epg-pinentry-mode 'loopback)

Next, disable the dialog you’re normally presented with to select an encryption key:

(setq epa-file-select-keys nil)

Setting epa-file-select-keys to nil also presupposes that you’ll be using symmetric encryption.

Finally, in order for epa-file-select-keys to take effect, set epa-file-encrypt-to as a directory-local variable:

((nil . ((epa-file-encrypt-to . "[email protected]"))))

If, like me, you’re also making use of git-auto-commit-mode, your .dir-locals.el might look like this:

((nil . ((eval git-auto-commit-mode 1)
         (epa-file-encrypt-to . "[email protected]"))))

Summary

So there you have it! If you want to make use of Emacs’ built-in GPG encryption capabilities to automatically encrypt *.gpg files when they’re saved, you need to:

  1. Generate, store, and distribute a GPG key that you can use everywhere you want to encrypt/decrypt your notes.
  2. Set the epg-pinentry-mode and epa-file-select-keys variables globally.
  3. Set the epa-file-encrypt-to on a per-file, or per-directory basis.
  4. C-x C-s and profit!