Storing your secrets in plain text is Bad Idea whether it’s your Vogon Poetry or your e-mail credentials. Depending on your level of paranoia (it’s not paranoia if they really are watching you…) the advice in this article may not be enough; but for most, though, keeping your secrets encrypted on your file system is an easy way of keeping your secrets secret.
Emacs, obviously, can do this for you, and in a variety of ways.
This article will teach you how to use Emacs’s native support for GnuPG – a package called EasyPG, or epa
– to both sign/verify and encrypt/decrypt files, and how you can use this knowledge to store secrets that Emacs can understand. I will also show you how to use the auth-source
package – a unified interface for different secrets backends – and how you can use it to automatically log in to various external services with public-private keys.
Keeping Secrets in Emacs with GnuPG & EasyPG
GNU Privacy Guard (GnuPG) is a powerful tool and a free implementation of the OpenPGP standard. It’s especially useful for both symmetric and asymmetric cryptography: whether you are signing binaries or archives; encrypting or decrypting files with keys; or merely symmetrically encrypting them with a pass phrase, GPG is simply a great tool to have around.
But GnuPG is also useful in Emacs. Emacs – as you would expect – has integrated support for basic GnuPG features through a built-in package called EasyPG.
With EasyPG you can both sign and verify files, and encrypt and decrypt them, both symmetrically with passphrases and asymmetrically with public-private keys.
GPG v1 versus GPG v2
You may find that gpg
cannot be found on your computer. This often happens as there is also a GPG version 2 named, aptly, gpg2
. You can customize the epg-gpg-program
variable to the name of the tool you want Emacs to use:
(setq epg-gpg-program "gpg2")
Problems in Emacs 29.1
There are known issues in Emacs 29.1 concerning GnuPG version 2.4.1 or higher. Downgrading to 2.4.0 or earlier fixes it.
Transparent File Cryptography with EasyPG
One of the nicest features of Emacs’s GnuPG support is that it transparently decrypts and re-encrypts files you open and save in Emacs.
The EasyPG package hooks into Emacs and will, transparently, detect GnuPG files. The variable auto-mode-alist
controls how Emacs assigns major modes when you open certain files; in this instance, any file that ends with .gpg
is treated as a GnuPG file in Emacs.
To test it out, open a file – such as /tmp/foobar.gpg
– write some text and then save it with C-x C-s
. Emacs will prompt you for a key (if you have any) or, if you don’t pick one, a pass phrase to symmetrically encrypt the file with.
If you then re-open it, you will be prompted for the same pass phrase and Emacs will decrypt it and open it.
The possibilities are endless. And, of course, you can nest the file extensions: open a .py.gpg
file and it is first decrypted and then the normal python-mode
machinery kicks in. The same with encrypted, compressed archives: open a .tar.gz.gpg
file and Emacs will decrypt and then open it with auto-compression-mode
.
Interactive Commands
There are a handful of interactive commands that help you use EasyPG:
Command | Description |
| List all the keys from the public/secret keyring |
M-x epa-verify-<region|file> | Verifies the current region/file |
M-x epa-sign-<region|file> | Signs the current region/file |
M-x epa-insert-keys | Insert one or more keys into the buffer |
M-x epa-decrypt-<region|file> | Decrypts the current region/file |
M-x epa-encrypt-<region|file> | Encrypts the current region/file |
Most are variations of the same theme and don’t require further explaining. Both M-x epa-list-keys
and M-x epa-list-secret-keys
list keys in your system’s keychains. You can also browse them with the Emacs Secrets package (see chapter below) or a tool that ships with your system such as Ubuntu’s seahorse
.
Dired
Thanks to the clever auto-mode-alist
system you can open .gpg
files in Dired as you would elsewhere. But Dired also comes with a couple of handy key bindings for interacting with EasyPG:
Key Binding | Description |
: d | Decrypt marked or selected |
: e | Encrypt marked or selected |
: s | Sign marked or selected |
: v | Signs the current buffer |
Dired is clever enough to apply the command to multiple files if you have marked files; if you don’t, it will use the file point is on.
Keep in mind that if you want to encrypt multiple files into one .gpg
file you will have to compress them first: press c
then enter the target filename Emacs should compress the marked files to. Emacs will pick the right compression that matches the file extension (.tar.gz
, .zip
, etc.) and then you can encrypt the archive.
Disabling External Pin Entry
You can force GPG to not use an external tool for pin entry. That is particularly useful if you don’t want the default GPG Agent pin entry tool to start, particularly if you want Emacs to handle the pin entry for you.
There are probably many ways of doing this (as it’s likely to depend on your distro and window manager) but the easiest thing to do is disable the agent info in Emacs only:
(setenv "GPG_AGENT_INFO" nil)
This will force Emacs to use its own internal password prompt instead of an external pin entry program.
Using Keys to Store Secrets
NOTE: Please keep in mind that you are taking security advice from an Emacs blogger and not a security maven. The instructions below are just a guideline to show you how to use Emacs’s GPG integration.
Like I mentioned above, it’s easy to transparently decrypt and encrypt files with a symmetric key but that’s an awful lot of hassle when you can use a public-private key pair instead. The benefit of the key is that you can keep it loaded into memory and let Emacs decrypt and re-encrypt files without prompting you for a password.
Creating a key
To get started you must first generate the key pair with gpg
:
$ gpg --gen-key
Follow the prompts to generate your key. I highly recommend you pick a pass phrase!
You can verify it is loaded into your system’s keychain by running:
M-x epa-list-secret-keys
in Emacs;
or gpg --list-secret-keys
on your command line, in which case it’ll look like this:
$ gpg --list-secret-keys
sec 2048R/5DB69AC1 2016-06-13
uid Cosmo Kramer (Kramerica Industries) <kramer@example.com>
ssb 2048R/02A89A28 2016-06-13
or using a UI program like seahorse
.
Exporting and Re-Importing a Key
Next, export the secret key to a file mykey.asc
to gpg
(using the key holder’s name, email or key ID):
$ gpg --armor --export-secret-keys Cosmo Kramer > mykey.asc
You can now, on a different machine, re-import the key, but you will also have to trust it again. You can pass the full name in quotes or the e-mail to gpg
and it will pick the right one. Here I edit a key based on the full name of the key holder and GPG is smart enough to figure out which one it is:
$ gpg --import mykey.asc
$ gpg --edit-key "Cosmo Kramer"
gpg> trust
Your decision? 5
Do you really want to set this key to ultimate trust? (y/N) y
gpg> quit
At this point you have a key and a way of exporting and re-importing it between computers; useful, if you use more than one, but optional. It goes without saying that if you lose your key you lose your encrypted data!
Encrypting Data with a Key
Armed with a key you can tell EasyPG that it should simply decrypt and re-encrypt with the secret keys in your keychain. There’s a special file local variable called epa-file-encrypt-to
that automatically picks the right key.
Here’s a simple example. Create an elisp file your-secrets.el
and enter the following:
# -*- epa-file-encrypt-to: ("kramer@example.com") -*-
(setq jabber-account-list ...)
(setq my-secret-password "rosebud")
Where kramer@example.com
is the example key we created earlier and the e-mail “recipient” we encrypt and decrypt against. Observe that we are finding a key based on the e-mail address alone as it’s human readable as opposed to an ID. Next, explicitly encrypt it with M-x epa-encrypt-file
and select the same key to encrypt with. When you try to save the encrypted file Emacs will automatically pick the right key.
Now you can load the file in your init.el
when you load Emacs:
(load-library "/path/to/your-secrets.el.gpg")
Emacs will ask for a pass phrase of the key it was encrypted with and then load the elisp file as though it were a normal file.
Storing Credentials with the Auth Source Package
This chapter builds on information in the section Using Keys to Store Secrets.
Auth Source is a generic interface for common backends such as your operating system’s Keychain and your local ~/.authinfo
or ~/.netrc
file.
Auth Source is supported by a variety of Emacs packages, but with the added benefit of having a fairly straightforward API if you do need to call it directly. Among the supported ones are: jabber.el
, GNUS, TRAMP, various internal network functions, LDAP (yes, Emacs has an LDAP client built in), and ERC.
Auth Source solves the problem of mapping passwords and usernames to hosts, and it even supports multiple backends if you have credentials in more than one place.
Debugging Authentication Issues
The first thing I want to mention is the debug variable. Debugging authentication problems is hard enough without adding another layer inbetween. To enable debug information set the auth-source-debug
to t
to enable or nil
to disable:
(setq auth-source-debug t)
This will echo a lot of additional, helpful, information to the *Messages*
buffer. Be sure to turn it off when you are done.
Another useful function to call is M-x auth-source-forget-all-cached
. Auth source will cache your credentials in Emacs; use this command to forget all the cached details.
Automatic Jabber Login
Here’s a common workflow: logging in to Google Hangouts/Chat with jabber.el
.
Consider the following jabber account:
(setq jabber-account-list
'(("<your-gmail-email>"
(:network-server . "talk.google.com")
(:port . 443)
(:connection-type . ssl))))
When you run M-x jabber-connect
you’ll be asked – if all goes well – for your password. Instead of having to type it every time you can store it encrypted on your filesystem and have Emacs fill it in automatically.
To do this we’ll need an .authinfo
file and a way of telling Emacs where it is. By default it will look in ~/.authinfo
and a few other places, but I prefer keeping it encrypted and under source control. So to tell auth-source
where to look for it you update the auth-sources
list variable:
(setq auth-sources
'((:source "~/.emacs.d/secrets/.authinfo.gpg")))
Change the filepath to one that works for you. Next, create the empty file as .authinfo.gpg
and add this line:
machine gmail.com login <your account name> port xmpp password <your secret password>
Replacing <your account name>
with the username only – i.e., johndoe
and not johndoe@gmail.com
. Replace <your secret password>
with your password and save the file and pick the key you created earlier.
Ensure the auth-sources
variable is set up and evaluated and then run M-x jabber-connect
again and – if you’ve set it up right – Emacs will decrypt your .authinfo.gpg
file – prompting you for your passphrase, once, if Emacs does not have the secret key in memory – and match the hostname and username against the entries in .authinfo.gpg
and send the password to Jabber.
And if things go wrong, refer to the Debugging Authentication Issues chapter above.
Now you can go ahead and extend this to your e-mails, to TRAMP (if you don’t use SSH keys) and so on applying the same principles. Emacs will keep the secret key in memory and apply it automatically and you won’t be badgered to enter a password over and over again any more.
One more useful thing about the auth-sources
variable: you can have more than one source. You can even use your OS’s keychain/agent as a source of keys.
Conclusion
Good news – your Vogon poetry’s safe. As you can see, with a bit of technical kowtowing with GPG and Emacs’s authentication machinery and you can automate away most of the tedium of credentials management. EasyPG and Auth Sources are both powerful tools that you should learn more about. In fact, I’ve barely scratched the surface and, like all things Emacs, everyone has their own special snowflake configuration so do let me know if you can think of interesting, time-saving workflows.