Setting up encrypted mails with gpg and mutt

Hi everybody!

I want to explain how to set up mutt to use gpg encryption for sending and receiving encrypted mails. Here are steps necessary for encrypted messaging.

Having a gpg key secret

First, you need to generate your gpg key for use with email. You may skip this step if you already have a gpg key.

Issue this command on your trusted desktop computer to generate your key.

gpg --gen-key

Follow the instruction. I suggest you to use your blinkenshell mail address.

Make a note on your gpg passphrase. Never forget the passphrase or your key will be unusable.

You may generate your gpg key on the server, but I don't recommend it. It's better to use your trusted desktop computer to generate gpg keys.

The process of generating key may take a bit of time. Finally, congratulations. Your first gpg key is generated.

Optional: Publishing gpg public key to keyserver

The next step to export the key to public keyserver.

This step is optional. There are considerations whether to publish the key or hosting the public key on your own server. I recommend hosting the public key on your own server instead of publishing the key to public keyserver.

The only way to inform the keyserver in case you decide to deprecate the key later will be to mark the key as revoked. There is no way to revoke a published key if access to the private key is lost. There is also an attack surface with key published on keyserver, such as public key signed with unusual large number of signatures. You've been warned!

If you have decided to publish the key to keyserver, here is how to do it. On your desktop, issue the following command.

gpg --list-secret-keys

Make a note on your key id associated with your email address. As a real example, my key id is 0xEC8239AAD21D8761.

pub   rsa4096/0xEC8239AAD21D8761 2014-06-27 [SC]
      Key fingerprint = 6D83 56C1 7AB9 1080 8901  F58A EC82 39AA D21D 8761
uid                   [ultimate] The Fuzzy Whirlpool Thunderstorm (My new 4096bit RSA key)
sub   rsa4096/0xD887856376FF7644 2014-06-27 [E]

To export the public key, type the following command.

gpg --keyserver KEYSERVER_HERE --send-keys YOURKEYID_HERE

Replace YOURKEYID_HERE with your own key id.

There are some well known public keyservers, such as keys.openpgp.org and keyserver.ubuntu.com. You can manually upload the key into those public keyservers using web interface. It doesn't matter which keyserver you choose, since those public keyservers do synchronize each others. The published key will be available on other keyservers after a while.

Optional: Importing secret key to the mail server

If you plan to do mail related stuff directly on the server, it would be convenient to have the key on the server. Make sure that you trust the server prior to placing the secret key on the server.

Export the secret key to file. Replace the key id with yours

gpg --output ~/mysecretkey.gpg --export-secret-keys YOUR_KEYID

Your secret key is now exported to file mysecretkey.gpg on your home directory. Now, transfer the secret key to the server. rsync, scp or sftp can be used for this purpose. Here on blinkenshell, ssh listens on non standard port (443 and 2222), so the port needs to be specified.

scp -P443 ~/mysecretkey.gpg mylogin@ssh.blinkenshell.org:~/

Your secret key is now available on your home directory on the server.

Now, connect via ssh to the server and import the secret key.

ssh -p 443 mylogin@ssh.blinkenshell.org

Issue the command to import the secret key

gpg --import ~/mysecretkey.gpg

pinentry will ask for passphrase. Fill the correct passphrase to import the secret key.

Make sure the key is imported correctly.

gpg --list-secret-keys

Congratulations, you have successfully imported your secret key on the server and you can do email related stuff on the server directly.

Not really necessary: Compiling mutt from source with support for tls, sasl, imap, and gpgme

Instead of doing manual compilation, it would be simple to use pre-installed mutt package. If it's not installed, you can simply install mutt using distro package manager easily.

Here are steps to compile mutt from source, in case you want the latest version which is not packaged by the distro, provided as reference.

Download mutt source code and signature. The latest version as of February 2022 is 2.2.0. Visit official mutt site to get the latest version.

wget https://bitbucket.org/mutt/mutt/downloads/mutt-2.2.0.tar.gz
wget https://bitbucket.org/mutt/mutt/downloads/mutt-2.2.0.tar.gz.asc

Get the key used to sign mutt release

wget http://www.mutt.org/keys/kevin.key
gpg --import ./kevin.key

Verify the integrity of the downloaded mutt source code.

gpg --verify mutt-2.2.0.tar.gz.asc mutt-2.2.0.tar.gz

Make sure the output says "Good signature from...". If it says "Bad signature...", repeat the download process.

Congratulations. You have verified the downloaded source code.

Now is time for mutt compilation and installation. You need development package installed: build-essential on Debian or Ubuntu.

To prevent terminal disconnection during build, run the build inside tmux or screen session.

tmux

Extract the downloaded mutt source code

tar -zxf mutt-2.2.0.tar.gz

Now, let's begin the compilation process.

Change working directory into mutt directory

cd mutt-2.2.0/

Define compilation options.

./configure --prefix=$HOME/.local '--with-mailpath=~/Maildir' \
'--with-domain=blinkenshell.org' '--with-gnutls' '--with-sasl' \
'--with-included-gettext' '--with-regex' \
'--enable-pop' '--enable-imap' '--enable-smtp' \
'--enable-gpgme' '--enable-hcache'

Begin compilation process.

time make

When compilation process is finished, install the compiled binary to your home directory.

make install

Now, add $HOME/.local/bin to your PATH environment variable.

export PATH="$HOME/.local/bin:$PATH"

You can make this environment variable persistent by adding the command to your ~/.profile

if [ -d $HOME/.local/bin ] ; then
PATH=$HOME/.local/bin:$PATH
fi

Congratulations, you have a working mutt installed on your home directory.

Mutt configuration

Let's configure mutt for sending and receiving encrypted mails. Create .muttrc file in your home directory.

touch ~/.muttrc

Create .muttrc/tmp directory for use with mutt.

mkdir -p .muttrc/tmp

Edit the content of .muttrc as follows.

# replace vim with your favorite text editor, for example nano or emacs.
set editor=vim
set hostname="blinkenshell.org"
# replace with your realname as used on your gpg key
set realname="The Fuzzy Whirlpool Thunderstorm"
set folder=~/Maildir
# set folder=imap://despina:143/
# replace with your imap username
set imap_user=whirlpool
set spoolfile=+INBOX
mailboxes =INBOX =family
set header_cache=~/.cache/mutt
# Enable keep alive for 10 minutes
# set imap_keepalive=300
# Check every 5 minutes for new mail
set mail_check=300
set record=+Sent
# smtp credentials here
set smtp_url=smtp://$imap_user@despina/
set ssl_force_tls=yes
set ssl_starttls=yes
# stuff related to crypto
set crypt_autosign=yes
set crypt_replysign=yes
set crypt_replysignencrypted=yes
set crypt_replyencrypt=yes
set pgp_use_gpg_agent=yes
set crypt_use_gpgme=yes
# replace D21D8761 with your gpg key id
set pgp_sign_as=D21D8761
set pgp_timeout=300
set tmpdir=~/.mutt/tmp

Accessing mailserver with mutt

Log in to your server. In the ssh shell, launch mutt by typing:

mutt

You'll be asked for certificate verification twice. Accept all ssl certificate verification by pressing 'a' button.

Mutt will ask a password to login with mailserver. Just type your shell password to access mailserver.

Password for whirlpool@despina:

Congratulations. You've successfully set up mutt on your server. Exit mutt by pressing 'q' button.

Verifying mutt configuration for encrypted messaging

Here you will send me an encrypted mail to verify mutt configuration. Get my public key by issuing the following command.

wget http://whirlpool.blinkenshell.org/pages/mypubkey.asc
gpg --import ./mypubkey.asc

Now, time to test the power of mutt. Launch mutt and compose a mail to me, by pressing 'm' button. Specify recipient by typing my email address.

whirlpool [at] blinkenshell [dot] org

When you're done typing, exit the text editor. Press 'p' for encryption options, choose both signing and encrypting by pressing 'b'. Finally, send your mail by pressing 'y'. Type your gpg passphrase when asked to encrypt and sign the message. Mutt will ask for smtp password to send the message. If mail is successfully sent, mutt will say 'Mail sent'.

Bonus: Storing imap / smtp as gpg-encrypted file

You may be tired of mutt asking password too much. You can store imap / smtp credential as encrypted file and having mutt decrypt the file and source its content on start.

Create ~/.mutt/.auth_credentials.txt with the following content.

set my_imap_passwd="IMAPPASSWORDGOESHERE"
set my_smtp_passwd="SMTPPASSWORDGOESHERE"
set imap_pass=$my_imap_passwd
set smtp_pass=$my_imap_passwd

Encrypt the file and delete the unencrypted file safely. The encrypted file will be saved as ~/.mutt/.auth_credentials.txt.gpg. shred command from coreutils will perform secure deletion of the unencrypted file.

gpg -e -r mylogin@blinkenshell.org ~/.mutt/.auth_credentials.txt
shred -u ~/.mutt/.auth_credentials.txt

Put additional configuration inside ~/.muttrc to decrypt the file containing smtp / imap password during mutt startup.

source "gpg -d ~/.mutt/.auth_credentials.txt.gpg |"

With this setup, mutt will decrypt the credentials during startup, so accessing imap / smtp server won't trigger multiple prompt for passphrase / credentials.

That's all.