The purpose of this guide is to show the configuration and usage of mutt with GnuPG. A working knowledge of mutt, gnupg,and concepts of mail security and encryption are assumed.
see (prerequisites)if you are not familiar with gpg.
Find your gpg.rc
Copy it someplace sane
cp /usr/share/doc/mutt-1.5.21/gpg.rc ~/.gpg.rc or cp `locate gpg.rc` ~/.gpgrc cp /usr/share/doc/mutt-1.5.21/gpg.rc ~/.mutt/gpg.rc
Make mutt aware of it by adding 'source $FILE' to your .muttrc:
echo "source ~/.gpg.rc" >> ~/.muttrc
The pgp menu (p) option in the compose menu will have an (a) option for pgp "sign as".
GPG variables you'll probably want to define in your muttrc
pgp_autosign pgp_replyencrypt pgp_replysign pgp_replysignencrypt pgp_veryfy_sig pgp_sign_as
See the manual for variable values or others variables.
For example, this page suggests:
set pgp_use_gpg_agent = yes set pgp_sign_as = 43A5CE95 set pgp_timeout = 3600 set crypt_autosign = yes set crypt_replyencrypt = yes
Mailing your key using mutt
- Launch mutt and compose an email.
- After you're finished and you're in the compose menu hit the "?" key to see a list of all keybindings.
- Search for "mail a PGP public key".
- Exit the help menu and hit the key combination it lists for that option.
- It will then prompt you "Please enter the key ID:". Enter the keyid (email works) and you'll be prompted with a key selection menu.
- Pick your key (it must be in your keyring).
- Follow the escape prompt in the context-help menu at the top of the screen.
- Hit "send". You will then have emailed your gpg key using mutt.
The CodeSourcery method of Mutt setup and explanation
These are the settings from the mutt-gnupg-howto. You can put these in some file, for example in ~/.mutt/crypto file, and source it in your main muttrc file with:
or you can directly copy and paste it in your muttrc.
Note that the following configuration will not work with GnuPG versions greater than 2.1.0 due to backwards incompatibility issues because the passphrase is piped over stdin. One solution is to enable the loopback pinentry mode in the gpg-agent configuration and update the mutt commands to use the --pinentry-mode loopback flag as described in Arch Linux's GnuPG Wiki Article.
If you're sharing the mutt configuration between multiple computers with conflicting GnuPG versions, see bamos' crypto.sh to conditionally set --pinentry-mode only when gpg supports it.
NOTE: The pgp_encrypt_only_command and pgp_encrypt_sign_command contain an instruction to also encrypt the message using the author's public key. That is the option,"--encrypt-to 0xC9C40C31". If you want to automatically encrypt messages to yourself (for the Sent folder, for example), replace 0xC9C40C31 with your public key's id. Otherwise, remove the entire --encrypt-to 0xC9C40C31. You will get an error message about not finding the public key if you leave it as-is.
set pgp_decode_command="gpg %?p?--passphrase-fd 0? --no-verbose --batch --output - %f" set pgp_verify_command="gpg --no-verbose --batch --output - --verify %s %f" set pgp_decrypt_command="gpg --passphrase-fd 0 --no-verbose --batch --output - %f" set pgp_sign_command="gpg --no-verbose --batch --output - --passphrase-fd 0 --armor --detach-sign --textmode %?a?-u %a? %f" set pgp_clearsign_command="gpg --no-verbose --batch --output - --passphrase-fd 0 --armor --textmode --clearsign %?a?-u %a? %f" set pgp_encrypt_only_command="pgpewrap gpg --batch --quiet --no-verbose --output - --encrypt --textmode --armor --always-trust --encrypt-to 0xC9C40C31 -- -r %r -- %f" set pgp_encrypt_sign_command="pgpewrap gpg --passphrase-fd 0 --batch --quiet --no-verbose --textmode --output - --encrypt --sign %?a?-u %a? --armor --always-trust --encrypt-to 0xC9C40C31 -- -r %r -- %f" set pgp_import_command="gpg --no-verbose --import -v %f" set pgp_export_command="gpg --no-verbose --export --armor %r" set pgp_verify_key_command="gpg --no-verbose --batch --fingerprint --check-sigs %r" set pgp_list_pubring_command="gpg --no-verbose --batch --with-colons --list-keys %r" set pgp_list_secring_command="gpg --no-verbose --batch --with-colons --list-secret-keys %r"
# specify the uid to use when encrypting/signing
# this set the number of seconds to keep in memory the passphrase used to encrypt/sign # the more the less secure it will be
# it's a regexp used against the GPG output: if it matches some line of the output # then mutt considers the message a good signed one (ignoring the GPG exit code)
set pgp_good_sign="^gpg: Good signature from"
# mutt uses by default PGP/GPG to sign/encrypt messages # if you want to use S-mime instead set the smime_is_default variable to yes
# automatically sign all outgoing messages
# sign only replies to signed messages
# automatically encrypt outgoing messages
# encrypt only replies to signed messages
# encrypt and sign replies to encrypted messages
# automatically verify the sign of a message when opened
The mutt UI idea while dealing with encrypted mails is to automatically decrypt an encrypted message when it is opened. In a similar way it will optionally verify the authenticity of a signed message (depending on the crypt_verify_sig variable) when it is opened.
The status flag defined in the $index_format variable for the index, will show a relevant flag for each signed/encrypted message. They are:
- s if the message is signed and not yet verified
- S if the message is signed and the signature is successfully verified
- P if the message is PGP encrypted
In order to be considered completely sure, all the parts of the message have to be signed. If this is not the case mutt won't consider the message completely sure, and the flag will stay "s": this happens for example when a signed message is processed by a mailing-list software and a trailing mailing-list signature is applied to it.
Publication of your public key
There are different public keyservers, each one implementing one or more different access methods: HKP, WWW, FTP, mail, LDAP. An important thing to understand about keyservers is that they're synchronized, i.e. they tend to share the same public keys.
So in order to get published your public key in just one of these you only need to publicize it in just one keyserver, the key will eventually be propagated through all the keyservers.
Here it is a list of public keyservers (from the default gpg.conf file):
hkp://subkeys.pgp.net hkp://wwwkeys.pgp.net mailto:email@example.com ldap://pgp.surfnet.nl:11370 ldap://keyserver.pgp.com
Add it to a keyserver via http://sks-keyservers.net/i/ or other method.
and the corresponding key will be published in the specified keyserver (and in all others). Now your public key is public, congratulations!
The publication on a public keyserver is not definitively the only method possible: there is the possibility to use a web page, to send it through ordinary mail or email, or via web. Note that all of these methods are subject to a man in the middle attack: the more the number of methods you'll use, the less are the chances that some very determined malicious individual will stole your identity. Note also that the shared publication of your public key highly decreases the possibility of your public key be compromised, since the attacker should compromise at the same time all the keyservers.
In case of web publication you can attach an header to your outgoing mail as this:
in order to inform your recipient of the web address of your public key. The content of the page can be generated with:
gpg --export --armor
In mutt you can set this with the command:
Or if you don't want to use the web publication method you can just use a keyserver lookup:
Retrieval of keys from a keyserver
In order to verify or decrypt a message you need the public key of the sender.
Manually you can do this in this way:
gpg --recv-keys <names>
or even with:
gpg --search-keys <names>
and then selecting the number of the public key you want to add to your local keyring.
You might need to configure GnuPG to automatically do it for you every time a private key is not present in the local keyring.
This comes in very handy with Mutt, as you won't have to go and download and import a key manually in another terminal. In order to do this, add this line to your ~/.gnupg/gpg.conf file:
keyserver <keyserver address> keyserver-options auto-key-retrieve
with the uri of your preferred keyserver. In this way every time a key is not present in your local keyring gnupg will try to fetch it from the keyserver specified in the gpg.conf file.
Verifying messages signatures
The %Z flag (status flag) in the $index_format tell you when a message is signed. If the message is signed (and it hasn't still been verified either it has a bad signature) a "s" character will appear in the corresponding line of the index, if the message signature has been verified then will appear a "S" character. In order to verify a message you need the corresponding public key of the sender being in your keyring, or setup gpg to automatically retrieve a corresponding key from a public keyserver (remember to setup the auto-key-retrieve keyserver-option as explained in the previous section).
In order to verify a message mutt runs the $pgp_verify_command and check the exit of the command.
The command in our case is specified as follows:
set pgp_verify_command="gpg --no-verbose --batch --output - --verify %s %f"
If $crypt_verify_sig is set to yes, mutt will run the pgp_verify_command on every opened message, and the output of this command will be displayed in the pager, before the message itself.
Verifying a message signature on the fly
You could be interested in verifying the signature of just a specific message. The following macros let you force the variable value of crypt_verify_sig to yes in order to get mutt verify the message, and then restore the previous value (you need mutt >= 1.5.12 with $my_variable support to get these macros working).
Please do not forget the "\" in the following macros code at the end of each line (or put all the text of each macro in one line).
macro index \Cv \ "<enter-command> set my_crypt_verify_sig=\$crypt_verify_sig<enter> \ <enter-command> set crypt_verify_sig=yes<enter> \ <display-message><enter-command> set crypt_verify_sig=\$my_crypt_verify_sig<enter>" \ 'Verify PGP signature and open the message' macro pager \Cv \ "<exit><enter-command> set my_crypt_verify_sig=\$crypt_verify_sig<enter> \ <enter-command> set crypt_verify_sig=yes<enter> \ <display-message><enter-command> set crypt_verify_sig=\$my_crypt_verify_sig<enter>" \ 'Verify PGP signature'
$pgp_sign_as let you specify the uid to use when signing (since you can have different uids depending on the context). The corresponding public key will be extracted from your current keyring. You can set up some hook to customize the uid to use according to each particular situation.
You can automatically sign all outgoing messages setting
or simply selecting the pgp-menu (bound to "p") in the compose menu. You can use send-hook or folder-hook to setup the security criterion in a context dependent fashion.
To automatically encrypt messages to specific recipients use
send-hook . 'reset pgp_autoencrypt' send-hook "!~l ~t onemail@example\\.org" "set crypt_autoencrypt crypt_autosign" send-hook "!~l ~t another@example\\.org" "set crypt_autoencrypt crypt_autosign"
where the first global send-hook always resets crypt settings and a following matching, if any, send-hook sets crypt for that recipient. Note the double escaped backslash inside double quotes, "\\". The !~l pattern is to not activate encryption if the mail is also addressed to a known mailing list.
gpg & mutt
In order to become familiar with issues around gpg & mutt, please read one or both of these documents:
- Understanding of mail encryption and the web of trust
- Have both mutt and gnupg installed and working properly.
- A keyring with both public and private keys.
You can list all the keys in your gnupg keyring with:
Typically the output consists of lines of the type:
pub 2048R/DEADBEEF 2010-05-01 [expired: 2012-04-30] uid Alice Glass <firstname.lastname@example.org> pub 2048R/1234ABCD 2012-12-18 [expires: 2014-12-18] uid Alice Glass <email@example.com>
The key ID (identifier) is the sequence of hexadecimal digits which comes after the "/", for example in these cases they are DEADBEEF and 1234ABCD. You should verify that your key is not expired.
To publicize your public key by sending it to a keyserver do this:
gpg --send-key <key id>
Before sending a key via email you need an "ascii armored" version:
gpg --armor --export YOURKEYID > username_pubkey.ascii